home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1995-05-17 | 171.7 KB | 5,319 lines
// copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT // see COPYRIGHT for reuse legalities // #import "WW3DCamera.h" #import "WWInterp.h" // this includes WWTCLKit.h #import "WW3DShape.h" #import "WW3DShader.h" #import "WW3DText.h" #import "RIBColor.h" #import "RIBTorus.h" #import "WW3DLight.h" #import "WW3DWell.h" #import "WWSceneClock.h" // has the sceneClock protocol - formalize this! #import "WWEveParser.h" // to work around NeXT's copyRIB: bug... #import <mach/cthreads.h> @implementation WW3DCamera + initialize { return [WW3DCamera setVersion:5], self; } static char errBuf[1024]; /* ========================================================================== subext() -- Remove extension from fname only if it is there. ========================================================================== */ static char *subext(fname, ext) register char *fname, *ext; { int fl, el; for ( fl = strlen(fname), el = strlen(ext); --el > -1 && --fl > -1 && fname[fl] == ext[el]; ) ; if (el == -1) { fname[fl] = '\0'; } return(fname); } /* ========================================================================== basename() -- deletes any prefix ending in `/' and the suffix. ========================================================================== */ static char *basename(str, sfx, dest) char *str, *sfx, *dest; { char temp[1024]; char *p, *p1; char *subext(); p = p1 = temp; strcpy(p, str); while (*p) { if (*p++ == '/') { p1 = p; } } strcpy (dest, subext(p1, sfx)); return(dest); } static int cmd_dumpRIBToFile(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "filename"; int num_args = 2; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me dumpRIBToFile:argv[1]]; return TCL_OK; } static int cmd_display(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me display]; return TCL_OK; } static int cmd_backgroundColor(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[{r g b}]"; NXColor backgroundColor; int argc2; char **argv2; float red, green, blue; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2) && (argc != 4)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { backgroundColor = [me backgroundColor]; sprintf(interp->result, "{%f %f %f}", NXRedComponent(backgroundColor), NXGreenComponent(backgroundColor), NXBlueComponent(backgroundColor)); return TCL_OK; } if (argc == 2) { Tcl_SplitList(interp, argv[1], &argc2, &argv2); if (argc2 != 3) { sprintf(errBuf, "USAGE: %s %s (colors should have 3 components)", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); if (argv2) { free(argv2); } return TCL_ERROR; } red = (float)atof(argv2[0]); green = (float)atof(argv2[1]); blue = (float)atof(argv2[2]); free(argv2); backgroundColor = NXConvertRGBAToColor(red, green, blue, 1.0); [me setBackgroundColor:backgroundColor]; backgroundColor = [me backgroundColor]; sprintf(interp->result, "{%f %f %f}", NXRedComponent(backgroundColor), NXGreenComponent(backgroundColor), NXBlueComponent(backgroundColor)); return TCL_OK; } if (argc == 4) { red = (float)atof(argv[1]); green = (float)atof(argv[2]); blue = (float)atof(argv[3]); backgroundColor = NXConvertRGBAToColor(red, green, blue, 1.0); [me setBackgroundColor:backgroundColor]; backgroundColor = [me backgroundColor]; sprintf(interp->result, "{%f %f %f}", NXRedComponent(backgroundColor), NXGreenComponent(backgroundColor), NXBlueComponent(backgroundColor)); return TCL_OK; } return TCL_ERROR; } static int cmd_renderStyle(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[PointCloud|WireFrame|ShadedWireFrame|FacetedSolids|SmoothSolids]"; int renderStyle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { renderStyle = [me renderStyle]; if (renderStyle == N3D_PointCloud) { sprintf(interp->result, "PointCloud"); return TCL_OK; } if (renderStyle == N3D_WireFrame) { sprintf(interp->result, "WireFrame"); return TCL_OK; } if (renderStyle == N3D_ShadedWireFrame) { sprintf(interp->result, "ShadedWireFrame"); return TCL_OK; } if (renderStyle == N3D_FacetedSolids) { sprintf(interp->result, "FacetedSolids"); return TCL_OK; } if (renderStyle == N3D_SmoothSolids) { sprintf(interp->result, "SmoothSolids"); return TCL_OK; } sprintf(interp->result, "Yikes! I have no mapping for renderStyle %d", renderStyle); return TCL_ERROR; } if (argc == 2) { if (!strcmp(argv[1], "PointCloud")) { [me setRenderStyle:N3D_PointCloud]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "WireFrame")) { [me setRenderStyle:N3D_WireFrame]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "ShadedWireFrame")) { [me setRenderStyle:N3D_ShadedWireFrame]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "FacetedSolids")) { [me setRenderStyle:N3D_FacetedSolids]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "SmoothSolids")) { [me setRenderStyle:N3D_SmoothSolids]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } sprintf(errBuf, "ERROR: unknown surface type <%s>\nUSAGE: %s %s", argv[1], argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } return TCL_ERROR; } static int cmd_movingRenderStyle(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[PointCloud|WireFrame|ShadedWireFrame|FacetedSolids|SmoothSolids]"; int movingRenderStyle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { movingRenderStyle = [me movingRenderStyle]; if (movingRenderStyle == N3D_PointCloud) { sprintf(interp->result, "PointCloud"); return TCL_OK; } if (movingRenderStyle == N3D_WireFrame) { sprintf(interp->result, "WireFrame"); return TCL_OK; } if (movingRenderStyle == N3D_ShadedWireFrame) { sprintf(interp->result, "ShadedWireFrame"); return TCL_OK; } if (movingRenderStyle == N3D_FacetedSolids) { sprintf(interp->result, "FacetedSolids"); return TCL_OK; } if (movingRenderStyle == N3D_SmoothSolids) { sprintf(interp->result, "SmoothSolids"); return TCL_OK; } sprintf(interp->result, "Yikes! I have no mapping for movingRenderStyle %d", movingRenderStyle); return TCL_ERROR; } if (argc == 2) { if (!strcmp(argv[1], "PointCloud")) { [me setMovingRenderStyle:N3D_PointCloud]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "WireFrame")) { [me setMovingRenderStyle:N3D_WireFrame]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "ShadedWireFrame")) { [me setMovingRenderStyle:N3D_ShadedWireFrame]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "FacetedSolids")) { [me setMovingRenderStyle:N3D_FacetedSolids]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "SmoothSolids")) { [me setMovingRenderStyle:N3D_SmoothSolids]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } sprintf(errBuf, "ERROR: unknown surface type <%s>\nUSAGE: %s %s", argv[1], argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } return TCL_ERROR; } static int cmd_tesselation(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[tesselation]"; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { sprintf(interp->result, "%f", [me tesselation]); return TCL_OK; } if (argc == 2) { [me setTesselation:(float)atof(argv[1])]; sprintf(interp->result, "%f", [me tesselation]); return TCL_OK; } return TCL_ERROR; } static int cmd_lowRezTesselation(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[lowRezTesselation]"; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { sprintf(interp->result, "%f", [me lowRezTesselation]); return TCL_OK; } if (argc == 2) { [me setLowRezTesselation:(float)atof(argv[1])]; sprintf(interp->result, "%f", [me lowRezTesselation]); return TCL_OK; } return TCL_ERROR; } static int cmd_fieldOfView(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "[fov]"; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != 1) && (argc != 2)) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (argc == 1) { sprintf(interp->result, "%f", [me fieldOfView]); return TCL_OK; } if (argc == 2) { [me setFieldOfViewByAngle:(float)atof(argv[1])]; sprintf(interp->result, "%f", [me fieldOfView]); return TCL_OK; } return TCL_ERROR; } static int cmd_setEyeAtTowardRoll(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "fromPoint toPoint aRollAngle"; int num_args = 4, argc2; RtPoint fromPoint, toPoint; float aRollAngle; char **argv2; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } Tcl_SplitList(interp, argv[1], &argc2, &argv2); // fromPoint if (argc2 != 3) { sprintf(errBuf, "USAGE: %s %s (points should have 3 components)", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); if (argv2) { free(argv2); } return TCL_ERROR; } N3D_XComp(fromPoint) = (float)atof(argv2[0]); N3D_YComp(fromPoint) = (float)atof(argv2[1]); N3D_ZComp(fromPoint) = (float)atof(argv2[2]); free(argv2); Tcl_SplitList(interp, argv[2], &argc2, &argv2); // fromPoint if (argc2 != 3) { sprintf(errBuf, "USAGE: %s %s (points should have 3 components)", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); if (argv2) { free(argv2); } return TCL_ERROR; } N3D_XComp(toPoint) = (float)atof(argv2[0]); N3D_YComp(toPoint) = (float)atof(argv2[1]); N3D_ZComp(toPoint) = (float)atof(argv2[2]); free(argv2); aRollAngle = (float)atof(argv[3]); [me setEyeAt:fromPoint toward:toPoint roll:aRollAngle]; return TCL_OK; } static int cmd_moveEyeBy(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "sDistance tDistance uDistance"; int num_args = 4; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me moveEyeBy:(float)atof(argv[1]) :(float)atof(argv[2]) :(float)atof(argv[3])]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } static int cmd_getEyePoint(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; RtPoint eyePoint, viewPoint; float aRollAngle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me getEyeAt:&eyePoint toward:&viewPoint roll:&aRollAngle]; sprintf(interp->result, "%f %f %f", N3D_XComp(eyePoint), N3D_YComp(eyePoint), N3D_ZComp(eyePoint)); return TCL_OK; } static int cmd_getViewPoint(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; RtPoint eyePoint, viewPoint; float aRollAngle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me getEyeAt:&eyePoint toward:&viewPoint roll:&aRollAngle]; sprintf(interp->result, "%f %f %f", N3D_XComp(viewPoint), N3D_YComp(viewPoint), N3D_ZComp(viewPoint)); return TCL_OK; } static int cmd_getRollAngle(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; RtPoint eyePoint, viewPoint; float aRollAngle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me getEyeAt:&eyePoint toward:&viewPoint roll:&aRollAngle]; sprintf(interp->result, "%f", aRollAngle); return TCL_OK; } static int cmd_getEyeAtTowardRoll(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; RtPoint eyePoint, viewPoint; float aRollAngle; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me getEyeAt:&eyePoint toward:&viewPoint roll:&aRollAngle]; sprintf(interp->result, "{%f %f %f} {%f %f %f} %f", N3D_XComp(eyePoint), N3D_YComp(eyePoint), N3D_ZComp(eyePoint), N3D_XComp(viewPoint), N3D_YComp(viewPoint), N3D_ZComp(viewPoint), aRollAngle); return TCL_OK; } static int cmd_setSurfaceTypeForAll(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "PointCloud|WireFrame|ShadedWireFrame|FacetedSolids|SmoothSolids"; int num_args = 2; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (!strcmp(argv[1], "PointCloud")) { [me setSurfaceTypeForAll:N3D_PointCloud chooseHider:YES]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "WireFrame")) { [me setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "ShadedWireFrame")) { [me setSurfaceTypeForAll:N3D_ShadedWireFrame chooseHider:YES]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "FacetedSolids")) { [me setSurfaceTypeForAll:N3D_FacetedSolids chooseHider:YES]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } if (!strcmp(argv[1], "SmoothSolids")) { [me setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } sprintf(errBuf, "ERROR: unknown surface type <%s>\nUSAGE: %s %s", argv[1], argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_removeDefaultLights(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me removeDefaultLights]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } static int cmd_restoreDefaultLights(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } [me restoreDefaultLights]; [[me delegate] cameraParametersWereUpdated:me]; return TCL_OK; } static int cmd_lightList(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1, i; id theLightList; N3DLight *light; N3DLightType lightType; char aBuf[MAXPATHLEN]; RtPoint from, to; RtFloat coneAngle, coneDelta, beamDistribution; NXColor color; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } theLightList = [me lightList]; Tcl_AppendResult(interp, "{", (char *)NULL); for (i = 0; i < [theLightList count]; i++) { light = [theLightList objectAt:i]; Tcl_AppendResult(interp, "{", (char *)NULL); sprintf(aBuf, "name %s", [light shapeName]); Tcl_AppendElement(interp, aBuf); lightType = [light type]; switch (lightType) { case N3D_AmbientLight: Tcl_AppendElement(interp, "type ambient"); break; case N3D_PointLight: Tcl_AppendElement(interp, "type point"); break; case N3D_DistantLight: Tcl_AppendElement(interp, "type distant"); break; case N3D_SpotLight: Tcl_AppendElement(interp, "type spot"); break; default: Tcl_AppendElement(interp, "type unknown"); break; } [light getFrom:&from to:&to]; sprintf(aBuf, "from %f %f %f", from[0], from[1], from[2]); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "to %f %f %f", to[0], to[1], to[2]); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "intensity %f", [light intensity]); Tcl_AppendElement(interp, aBuf); [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; sprintf(aBuf, "coneAngle %f", coneAngle); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "coneDelta %f", coneDelta); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "beamDistribution %f", beamDistribution); Tcl_AppendElement(interp, aBuf); color = [light color]; sprintf(aBuf, "color %f %f %f", NXRedComponent(color), NXGreenComponent(color), NXBlueComponent(color)); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "isGlobal %d", (int)[light isGlobal]); Tcl_AppendElement(interp, aBuf); Tcl_AppendResult(interp, "}", (char *)NULL); } Tcl_AppendResult(interp, "}", (char *)NULL); return TCL_OK; } static int cmd_otherLightList(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1, i; id theLightList; N3DLight *light; N3DLightType lightType; char aBuf[MAXPATHLEN]; RtPoint from, to; RtFloat coneAngle, coneDelta, beamDistribution; NXColor color; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } theLightList = [me otherLightList]; Tcl_AppendResult(interp, "{", (char *)NULL); for (i = 0; i < [theLightList count]; i++) { light = [theLightList objectAt:i]; Tcl_AppendResult(interp, "{", (char *)NULL); sprintf(aBuf, "name %s", [light shapeName]); Tcl_AppendElement(interp, aBuf); lightType = [light type]; switch (lightType) { case N3D_AmbientLight: Tcl_AppendElement(interp, "type ambient"); break; case N3D_PointLight: Tcl_AppendElement(interp, "type point"); break; case N3D_DistantLight: Tcl_AppendElement(interp, "type distant"); break; case N3D_SpotLight: Tcl_AppendElement(interp, "type spot"); break; default: Tcl_AppendElement(interp, "type unknown"); break; } [light getFrom:&from to:&to]; sprintf(aBuf, "from %f %f %f", from[0], from[1], from[2]); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "to %f %f %f", to[0], to[1], to[2]); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "intensity %f", [light intensity]); Tcl_AppendElement(interp, aBuf); [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; sprintf(aBuf, "coneAngle %f", coneAngle); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "coneDelta %f", coneDelta); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "beamDistribution %f", beamDistribution); Tcl_AppendElement(interp, aBuf); color = [light color]; sprintf(aBuf, "color %f %f %f", NXRedComponent(color), NXGreenComponent(color), NXBlueComponent(color)); Tcl_AppendElement(interp, aBuf); sprintf(aBuf, "isGlobal %d", (int)[light isGlobal]); Tcl_AppendElement(interp, aBuf); Tcl_AppendResult(interp, "}", (char *)NULL); } Tcl_AppendResult(interp, "}", (char *)NULL); return TCL_OK; } static int cmd_addAmbientLight(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name intensity [pathToParent]"; int num_args = 3; WW3DLight *light; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != num_args) && (argc != (num_args+1))) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } light = [[[WW3DLight alloc] init] makeAmbientWithIntensity:(RtFloat)atof(argv[2])]; [light setShapeName:argv[1]]; if (argc == (num_args + 1)) // local, visible light { if (![me addLocalLight:light usingPath:argv[num_args]]) { sprintf(errBuf, "unable to add local ambient light %s as a child of shape %s", argv[1], argv[num_args]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } } else // regular global light { [me addLight:light]; } return TCL_OK; } static int cmd_addPointLight(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name fromX fromY fromZ intensity [pathToParent]"; int num_args = 6; RtPoint from; WW3DLight *light; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != num_args) && (argc != (num_args+1))) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } from[0] = (RtFloat)atof(argv[2]); from[1] = (RtFloat)atof(argv[3]); from[2] = (RtFloat)atof(argv[4]); light = [[[WW3DLight alloc] init] makePointFrom:from intensity:(RtFloat)atof(argv[4])]; [light setShapeName:argv[1]]; if (argc == (num_args + 1)) // local, visible light { if (![me addLocalLight:light usingPath:argv[num_args]]) { sprintf(errBuf, "unable to add local point light %s as a child of shape %s", argv[1], argv[num_args]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } } else // regular global light { [me addLight:light]; } return TCL_OK; } static int cmd_addDistantLight(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name fromX fromY fromZ toX toY toZ intensity [pathToParent]"; int num_args = 9; RtPoint from, to; WW3DLight *light; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != num_args) && (argc != (num_args+1))) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } from[0] = (RtFloat)atof(argv[2]); from[1] = (RtFloat)atof(argv[3]); from[2] = (RtFloat)atof(argv[4]); to[0] = (RtFloat)atof(argv[5]); to[1] = (RtFloat)atof(argv[6]); to[2] = (RtFloat)atof(argv[7]); light = [[[WW3DLight alloc] init] makeDistantFrom:from to:to intensity:(RtFloat)atof(argv[8])]; [light setShapeName:argv[1]]; if (argc == (num_args + 1)) // local, visible light { if (![me addLocalLight:light usingPath:argv[num_args]]) { sprintf(errBuf, "unable to add local distant light %s as a child of shape %s", argv[1], argv[num_args]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } } else // regular global light { [me addLight:light]; } return TCL_OK; } static int cmd_addSpotLight(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name fromX fromY fromZ toX toY toZ coneAngle coneDelta beamDistribution intensity [pathToParent]"; int num_args = 12; RtPoint from, to; WW3DLight *light; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if ((argc != num_args) && (argc != (num_args+1))) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } from[0] = (RtFloat)atof(argv[2]); from[1] = (RtFloat)atof(argv[3]); from[2] = (RtFloat)atof(argv[4]); to[0] = (RtFloat)atof(argv[5]); to[1] = (RtFloat)atof(argv[6]); to[2] = (RtFloat)atof(argv[7]); light = [[[WW3DLight alloc] init] makeSpotFrom:from to:to coneAngle:(RtFloat)atof(argv[8]) coneDelta:(RtFloat)atof(argv[9]) beamDistribution:(RtFloat)atof(argv[10]) intensity:(RtFloat)atof(argv[11])]; [light setShapeName:argv[1]]; if (argc == (num_args + 1)) // local, visible light { if (![me addLocalLight:light usingPath:argv[num_args]]) { sprintf(errBuf, "unable to add local point light %s as a child of shape %s", argv[1], argv[num_args]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } } else // regular global light { [me addLight:light]; } return TCL_OK; } static int cmd_setLightIntensity(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name intensity"; int num_args = 3, i; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setIntensity:(RtFloat)atof(argv[2])]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setIntensity:(RtFloat)atof(argv[2])]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set intensity...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightType(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name type"; int num_args = 3, i; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; N3DLightType lightType = N3D_AmbientLight; BOOL validLightType = NO; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } if (!strcmp(argv[2], "ambient")) { lightType = N3D_AmbientLight; validLightType = YES; } if (!strcmp(argv[2], "point")) { lightType = N3D_PointLight; validLightType = YES; } if (!strcmp(argv[2], "distant")) { lightType = N3D_DistantLight; validLightType = YES; } if (!strcmp(argv[2], "spot")) { lightType = N3D_SpotLight; validLightType = YES; } if (!validLightType) { sprintf(errBuf, "%s is not a valid light type (ambient|point|distant|spot)", argv[2]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setType:lightType]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setType:lightType]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set type...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightFrom(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name fromX fromY fromZ"; int num_args = 5, i; RtPoint from; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } from[0] = (RtFloat)atof(argv[2]); from[1] = (RtFloat)atof(argv[3]); from[2] = (RtFloat)atof(argv[4]); for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setFrom:from]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setFrom:from]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set from point...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightTo(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name toX toY toZ"; int num_args = 5, i; RtPoint from, to; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getFrom:&from to:&to]; to[0] = (RtFloat)atof(argv[2]); to[1] = (RtFloat)atof(argv[3]); to[2] = (RtFloat)atof(argv[4]); [light setFrom:from to:to]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getFrom:&from to:&to]; to[0] = (RtFloat)atof(argv[2]); to[1] = (RtFloat)atof(argv[3]); to[2] = (RtFloat)atof(argv[4]); [light setFrom:from to:to]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set to point...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightColor(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name r g b"; int num_args = 5, i; NXColor color; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } color = NXConvertRGBToColor((float)atof(argv[2]), (float)atof(argv[3]), (float)atof(argv[4])); for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setColor:color]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light setColor:color]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set color...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightConeAngleConeDeltaBeamDistribution(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name coneAngle coneDelta beamDistribution"; int num_args = 5, i; RtFloat coneAngle, coneDelta, beamDistribution; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { coneAngle = (RtFloat)atof(argv[2]); coneDelta = (RtFloat)atof(argv[3]); beamDistribution = (RtFloat)atof(argv[4]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { coneAngle = (RtFloat)atof(argv[2]); coneDelta = (RtFloat)atof(argv[3]); beamDistribution = (RtFloat)atof(argv[4]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set coneAngle, coneDelta, beamDistribution...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightConeAngle(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name coneAngle"; int num_args = 3, i; RtFloat coneAngle, coneDelta, beamDistribution; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; coneAngle = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; coneAngle = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set coneAngle...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightConeDelta(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name coneDelta"; int num_args = 3, i; RtFloat coneAngle, coneDelta, beamDistribution; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; coneDelta = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; coneDelta = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set coneDelta...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_setLightBeamDistribution(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "name beamDistribution"; int num_args = 3, i; RtFloat coneAngle, coneDelta, beamDistribution; WW3DLight *light; id lightList = [me lightList]; id otherLightList = [me otherLightList]; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; beamDistribution = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } for (i = 0; i < [otherLightList count]; i++) { light = [otherLightList objectAt:i]; if (!strcmp(argv[1], [light shapeName])) { [light getConeAngle:&coneAngle coneDelta:&coneDelta beamDistribution:&beamDistribution]; beamDistribution = (RtFloat)atof(argv[2]); [light setConeAngle:coneAngle coneDelta:coneDelta beamDistribution:beamDistribution]; return TCL_OK; } } sprintf(errBuf, "no light named %s - unable to set beamDistribution...", argv[1]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } static int cmd_removeLight(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { int i; sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); for (i = 1; i < argc; i++) { if (![me removeLightNamed:argv[i]]) { sprintf(errBuf, "no light named %s - no further light removal done...", argv[i]); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } } return TCL_OK; } static int cmd_rotateAroundY(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = "u", **argv2, *str; int num_args = 2, argc2; RtPoint originalView; RtPoint originalEye, newEye; double u, radius, radiusSq; RtFloat originalRollAngle; //sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); //[[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } // u varies from 0 to 1, and describes a perfect circle around the original look at point. // we want to stay at the same Y point, and move around in a circle, such that the radius // of the circle we're describing stays constant. // we just want to set a new eye point and then reset the viewpoint to be the same as it had been. u = (float)atof(argv[1]); // need to grab "startCam(eyePoint)", which is a list str = [[me tclInterp] getVar2:"startCam" :"eyePoint"]; if (!str) { sprintf(errBuf, "startCam(viewPoint) is no defined - unable to interpolate"); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } Tcl_SplitList(interp, str, &argc2, &argv2); if (argc2 != 3) { sprintf(errBuf, "startCam(eyePoint) is supposed to have 3 elements, not %d", argc2); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } N3D_XComp(originalEye) = (float)atof(argv2[0]); N3D_YComp(originalEye) = (float)atof(argv2[1]); N3D_ZComp(originalEye) = (float)atof(argv2[2]); // need to grab "startCam(viewPoint)", which is a list str = [[me tclInterp] getVar2:"startCam" :"viewPoint"]; if (!str) { sprintf(errBuf, "startCam(viewPoint) is no defined - unable to interpolate"); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } Tcl_SplitList(interp, str, &argc2, &argv2); if (argc2 != 3) { sprintf(errBuf, "startCam(viewPoint) is supposed to have 3 elements, not %d", argc2); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } N3D_XComp(originalView) = (float)atof(argv2[0]); N3D_YComp(originalView) = (float)atof(argv2[1]); N3D_ZComp(originalView) = (float)atof(argv2[2]); radiusSq = ((N3D_XComp(originalEye) - N3D_XComp(originalView)) * (N3D_XComp(originalEye) - N3D_XComp(originalView))) + ((N3D_ZComp(originalEye) - N3D_ZComp(originalView)) * (N3D_ZComp(originalEye) - N3D_ZComp(originalView))); radius = sqrt(radiusSq); NXLogError("radius == %f\n", radius); N3D_XComp(newEye) = N3D_XComp(originalView) + ((N3D_XComp(originalEye) - N3D_XComp(originalView)) * cos(2 * PI * u)); N3D_YComp(newEye) = N3D_YComp(originalEye); N3D_ZComp(newEye) = N3D_ZComp(originalView) + ((N3D_ZComp(originalEye) - N3D_ZComp(originalView)) * sin(2 * PI * u)); // need to grab "startCam(rollAngle)" str = [[me tclInterp] getVar2:"startCam" :"rollAngle"]; originalRollAngle = (RtFloat)atof(str); [me setEyeAt:newEye toward:originalView roll:originalRollAngle]; return TCL_OK; } static int cmd_noop(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { sprintf(errBuf, "WW3DCamera's interp evaluating %s...", argv[0]); [[me statusText] setStringValue:errBuf]; [[me statusText] display]; NXPing(); return TCL_OK; } #if 0 static int cmd_(me, interp, argc, argv) WW3DCamera *me; Tcl_Interp *interp; int argc; char **argv; { char *my_args = ""; int num_args = 1; if (argc != num_args) { sprintf(errBuf, "USAGE: %s %s", argv[0], my_args); Tcl_AppendResult(interp, errBuf, (char *)NULL); return TCL_ERROR; } return TCL_OK; } #endif - initInterp { [tclInterp addCommand:"dumpRIBToFile" :cmd_dumpRIBToFile :self]; [tclInterp addCommand:"display" :cmd_display :self]; [tclInterp addCommand:"renderStyle" :cmd_renderStyle :self]; [tclInterp addCommand:"movingRenderStyle" :cmd_movingRenderStyle :self]; [tclInterp addCommand:"tesselation" :cmd_tesselation :self]; [tclInterp addCommand:"lowRezTesselation" :cmd_lowRezTesselation :self]; [tclInterp addCommand:"backgroundColor" :cmd_backgroundColor :self]; [tclInterp addCommand:"fieldOfView" :cmd_fieldOfView :self]; [tclInterp addCommand:"setEyeAt:toward:roll:" :cmd_setEyeAtTowardRoll :self]; [tclInterp addCommand:"setEyeAtTowardRoll" :cmd_setEyeAtTowardRoll :self]; [tclInterp addCommand:"moveEyeBy:::" :cmd_moveEyeBy :self]; [tclInterp addCommand:"moveEyeBy" :cmd_moveEyeBy :self]; [tclInterp addCommand:"setSurfaceTypeForAll" :cmd_setSurfaceTypeForAll :self]; [tclInterp addCommand:"getEyePoint" :cmd_getEyePoint :self]; [tclInterp addCommand:"getViewPoint" :cmd_getViewPoint :self]; [tclInterp addCommand:"getRollAngle" :cmd_getRollAngle :self]; [tclInterp addCommand:"getEyeAt:toward:roll:" :cmd_getEyeAtTowardRoll :self]; [tclInterp addCommand:"getEyeAtTowardRoll" :cmd_getEyeAtTowardRoll :self]; [tclInterp addCommand:"removeDefaultLights" :cmd_removeDefaultLights :self]; [tclInterp addCommand:"restoreDefaultLights" :cmd_restoreDefaultLights :self]; [tclInterp addCommand:"lightList" :cmd_lightList :self]; [tclInterp addCommand:"otherLightList" :cmd_otherLightList :self]; [tclInterp addCommand:"localLightList" :cmd_otherLightList :self]; [tclInterp addCommand:"addAmbientLight" :cmd_addAmbientLight :self]; [tclInterp addCommand:"addPointLight" :cmd_addPointLight :self]; [tclInterp addCommand:"addDistantLight" :cmd_addDistantLight :self]; [tclInterp addCommand:"addSpotLight" :cmd_addSpotLight :self]; [tclInterp addCommand:"setLightIntensity" :cmd_setLightIntensity :self]; [tclInterp addCommand:"setLightType" :cmd_setLightType :self]; [tclInterp addCommand:"setLightFrom" :cmd_setLightFrom :self]; [tclInterp addCommand:"setLightTo" :cmd_setLightTo :self]; [tclInterp addCommand:"setLightColor" :cmd_setLightColor :self]; [tclInterp addCommand:"setLightConeAngleConeDeltaBeamDistribution" :cmd_setLightConeAngleConeDeltaBeamDistribution :self]; [tclInterp addCommand:"setLightConeAngle" :cmd_setLightConeAngle :self]; [tclInterp addCommand:"setLightConeDelta" :cmd_setLightConeDelta :self]; [tclInterp addCommand:"setLightBeamDistribution" :cmd_setLightBeamDistribution :self]; [tclInterp addCommand:"removeLight" :cmd_removeLight :self]; [tclInterp addCommand:"rotateAroundY" :cmd_rotateAroundY :self]; [tclInterp addCommand:"askModel" :cmd_noop :self]; [tclInterp addCommand:"noop" :cmd_noop :self]; return self; } - setupDefaultLights { RtPoint lFromP = {0.5,0.5,-0.75}; RtPoint lToP = {0, 0, 0}; // ambient light ambientLight=[[WW3DLight alloc] init]; [ambientLight setShapeName:"ambientLight"]; [ambientLight makeAmbientWithIntensity:0.3]; [self addLight:ambientLight]; // distant light rightLight=[[WW3DLight alloc] init]; [rightLight setShapeName:"rightDistantLight"]; [rightLight makeDistantFrom:lFromP to:lToP intensity:0.7]; [self addLight:rightLight]; // point light //N3D_XComp( lFromP ) = -0.5; //N3D_YComp( lFromP ) = -0.5; //leftLight=[[WW3DLight alloc] init]; //[leftLight setShapeName:"leftPointLight"]; //[leftLight makePointFrom:lFromP intensity:0.7]; //[self addLight:leftLight]; defaultLightsInUse = YES; return self; } - restoreDefaultLights { if (!defaultLightsInUse) { [self addLight:ambientLight]; [self addLight:rightLight]; //[self addLight:leftLight]; defaultLightsInUse = YES; } return self; } - removeDefaultLights { if (defaultLightsInUse) { [self removeLight:ambientLight]; [self removeLight:rightLight]; [self removeLight:leftLight]; defaultLightsInUse = NO; } return self; } - removeLightNamed:(const char *)lightName { int i; id light; for (i = 0; i < [lightList count]; i++) { light = [lightList objectAt:i]; if (!strcmp(lightName, [light shapeName])) { [self removeLight:light]; return self; } } return nil; } - setFieldOfViewByAngle:(float)viewAngle { char buf[128]; [super setFieldOfViewByAngle:viewAngle]; sprintf(buf, "%f", viewAngle); [tclInterp setVar2:"cam" :"fieldOfView" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } char *ReadOnlyWriteProc(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { return "this is a read-only variable"; } char *WriteProcForInterpolationProc(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { // when a new interpolation proc is defined, there are several things we want to do. // first of all, we want to make sure that it's valid: // - a valid interpolation proc only has one argument: u // the other thing we might want to do is update the inspector panel (if we have one) about the contents of this guy... return NULL; } // someone is writing a new value for the cam(movingStyle) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForRenderStyle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; id me; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; me = [(WWTCLVarTrace *)clientData datum]; if (varString) { if (!strcmp(varString, "PointCloud")) { [me setRenderStyle:N3D_PointCloud]; return NULL; } if (!strcmp(varString, "WireFrame")) { [me setRenderStyle:N3D_WireFrame]; return NULL; } if (!strcmp(varString, "ShadedWireFrame")) { [me setRenderStyle:N3D_ShadedWireFrame]; return NULL; } if (!strcmp(varString, "FacetedSolids")) { [me setRenderStyle:N3D_FacetedSolids]; return NULL; } if (!strcmp(varString, "SmoothSolids")) { [me setRenderStyle:N3D_SmoothSolids]; return NULL; } } return "invalid value for \"cam(renderStyle)\"; must be on of PointCloud|WireFrame|ShadedWireFrame|FacetedSolids|SmoothSolids"; } // someone is reading a value for the cam(renderStyle) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForRenderStyle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { int renderStyle; id me; renderStyle = [[(WWTCLVarTrace *)clientData datum] renderStyle]; me = [(WWTCLVarTrace *)clientData datum]; if (renderStyle == N3D_PointCloud) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"PointCloud"]; return NULL; } if (renderStyle == N3D_WireFrame) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"WireFrame"]; return NULL; } if (renderStyle == N3D_ShadedWireFrame) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"ShadedWireFrame"]; return NULL; } if (renderStyle == N3D_FacetedSolids) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"FacetedSolids"]; return NULL; } if (renderStyle == N3D_SmoothSolids) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"SmoothSolids"]; return NULL; } return NULL; } // someone is writing a new value for the cam(movingStyle) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForMovingRenderStyle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; id me; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; me = [(WWTCLVarTrace *)clientData datum]; if (varString) { if (!strcmp(varString, "PointCloud")) { [me setMovingRenderStyle:N3D_PointCloud]; return NULL; } if (!strcmp(varString, "WireFrame")) { [me setMovingRenderStyle:N3D_WireFrame]; return NULL; } if (!strcmp(varString, "ShadedWireFrame")) { [me setMovingRenderStyle:N3D_ShadedWireFrame]; return NULL; } if (!strcmp(varString, "FacetedSolids")) { [me setMovingRenderStyle:N3D_FacetedSolids]; return NULL; } if (!strcmp(varString, "SmoothSolids")) { [me setMovingRenderStyle:N3D_SmoothSolids]; return NULL; } } return "invalid value for \"cam(movingRenderStyle)\"; must be on of PointCloud|WireFrame|ShadedWireFrame|FacetedSolids|SmoothSolids"; } // someone is reading a value for the cam(MovingRenderStyle) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForMovingRenderStyle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { int movingRenderStyle; movingRenderStyle = [[(WWTCLVarTrace *)clientData datum] movingRenderStyle]; if (movingRenderStyle == N3D_PointCloud) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"PointCloud"]; return NULL; } if (movingRenderStyle == N3D_WireFrame) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"WireFrame"]; return NULL; } if (movingRenderStyle == N3D_ShadedWireFrame) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"ShadedWireFrame"]; return NULL; } if (movingRenderStyle == N3D_FacetedSolids) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"FacetedSolids"]; return NULL; } if (movingRenderStyle == N3D_SmoothSolids) { [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:"SmoothSolids"]; return NULL; } return NULL; } // someone is writing a new value for the cam(tesselation) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForTesselation(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float tesselation = 32.; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &tesselation); [[(WWTCLVarTrace *)clientData datum] setTesselation:tesselation]; return NULL; } // someone is reading a value for the cam(tesselation) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForTesselation(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float tesselation; tesselation = [[(WWTCLVarTrace *)clientData datum] tesselation]; sprintf(buf, "%f", tesselation); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } // someone is writing a new value for the cam(lowRezTesselation) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForLowRezTesselation(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float lowRezTesselation = 16.; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &lowRezTesselation); [[(WWTCLVarTrace *)clientData datum] setLowRezTesselation:lowRezTesselation]; return NULL; } // someone is reading a value for the cam(tesselation) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForLowRezTesselation(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float lowRezTesselation; lowRezTesselation = [[(WWTCLVarTrace *)clientData datum] lowRezTesselation]; sprintf(buf, "%f", lowRezTesselation); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } // someone is writing a new value for the cam(fieldOfView) parameter, so we need // to update the WW3DCamera to reflect that new value... // really should constrain fov to be from <0 && <180 char *WriteProcForFieldOfViewByAngle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float fieldOfView = 45.; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &fieldOfView); [[(WWTCLVarTrace *)clientData datum] setFieldOfViewByAngle:fieldOfView]; return NULL; } // someone is reading a value for the cam(fieldOfView) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFieldOfViewByAngle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float fieldOfView; fieldOfView = [[(WWTCLVarTrace *)clientData datum] fieldOfView]; sprintf(buf, "%f", fieldOfView); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - setEyeAt:(RtPoint)fromPoint toward:(RtPoint)toPoint roll:(float)aRollAngle; { char buf[384]; [super setEyeAt:fromPoint toward:toPoint roll:aRollAngle]; sprintf(buf, "%f %f %f", N3D_XComp(fromPoint), N3D_YComp(fromPoint), N3D_ZComp(fromPoint)); [tclInterp setVar2:"cam" :"eyePoint" toValue:buf]; sprintf(buf, "%f %f %f", N3D_XComp(toPoint), N3D_YComp(toPoint), N3D_ZComp(toPoint)); [tclInterp setVar2:"cam" :"viewPoint" toValue:buf]; sprintf(buf, "%f", aRollAngle); [tclInterp setVar2:"cam" :"rollAngle" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(eyePoint) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForEyePoint(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString, **argv; int argc; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; Tcl_SplitList(interp, varString, &argc, &argv); // fromPoint if (argc != 3) { NXLogError("cam(eyePoint) should be a tcl list with 3 components, not <%s>\n", varString); if (argv) { free(argv); } return NULL; } N3D_XComp(anEyePoint) = (float)atof(argv[0]); N3D_YComp(anEyePoint) = (float)atof(argv[1]); N3D_ZComp(anEyePoint) = (float)atof(argv[2]); free(argv); [[(WWTCLVarTrace *)clientData datum] setEyeAt:anEyePoint toward:aViewPoint roll:aRollAngle]; return NULL; } // someone is reading a value for the cam() parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForEyePoint(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[384]; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; sprintf(buf, "%f %f %f", N3D_XComp(anEyePoint), N3D_YComp(anEyePoint), N3D_ZComp(anEyePoint)); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } // someone is writing a new value for the cam(viewPoint) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForViewPoint(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString, **argv; int argc; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; Tcl_SplitList(interp, varString, &argc, &argv); // viewPoint if (argc != 3) { NXLogError("cam(viewPoint) should be a tcl list with 3 components, not <%s>\n", varString); if (argv) { free(argv); } return NULL; } N3D_XComp(aViewPoint) = (float)atof(argv[0]); N3D_YComp(aViewPoint) = (float)atof(argv[1]); N3D_ZComp(aViewPoint) = (float)atof(argv[2]); free(argv); [[(WWTCLVarTrace *)clientData datum] setEyeAt:anEyePoint toward:aViewPoint roll:aRollAngle]; return NULL; } // someone is reading a value for the cam(viewPoint) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForViewPoint(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[384]; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; sprintf(buf, "%f %f %f", N3D_XComp(aViewPoint), N3D_YComp(aViewPoint), N3D_ZComp(aViewPoint)); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } // someone is writing a new value for the cam(rollAngle) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForRollAngle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; aRollAngle = (float)atof(varString); [[(WWTCLVarTrace *)clientData datum] setEyeAt:anEyePoint toward:aViewPoint roll:aRollAngle]; return NULL; } // someone is reading a value for the cam(rollAngle) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForRollAngle(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[384]; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; // get current values [[(WWTCLVarTrace *)clientData datum] getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; sprintf(buf, "%f", aRollAngle); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (RtFloat)fStop { return fStop; } - setFStop:(float)newFStop { char buf[128]; fStop = newFStop; sprintf(buf, "%f", fStop); [tclInterp setVar2:"cam" :"fStop" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(fStop) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForFStop(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float fStop = 1.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &fStop); [[(WWTCLVarTrace *)clientData datum] setFStop:fStop]; return NULL; } // someone is reading a value for the cam(fStop) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFStop(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float fStop; fStop = [[(WWTCLVarTrace *)clientData datum] fStop]; sprintf(buf, "%f", fStop); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (RtFloat)focalLength { return focalLength; } - setFocalLength:(float)newFocalLength { char buf[128]; focalLength = newFocalLength; sprintf(buf, "%f", focalLength); [tclInterp setVar2:"cam" :"focalLength" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(fStop) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForFocalLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float focalLength = 1.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &focalLength); [[(WWTCLVarTrace *)clientData datum] setFocalLength:focalLength]; return NULL; } // someone is reading a value for the cam(fStop) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFocalLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float focalLength; focalLength = [[(WWTCLVarTrace *)clientData datum] focalLength]; sprintf(buf, "%f", focalLength); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (RtFloat)focalDistance { return focalDistance; } - setFocalDistance:(float)newFocalDistance { char buf[128]; if (newFocalDistance > 0) { focalDistance = newFocalDistance; sprintf(buf, "%f", focalDistance); [tclInterp setVar2:"cam" :"focalDistance" toValue:buf]; [delegate cameraParametersWereUpdated:self]; } return self; } // someone is writing a new value for the cam(focalDistance) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForFocalDistance(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float focalDistance = 1.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &focalDistance); [[(WWTCLVarTrace *)clientData datum] setFocalDistance:focalDistance]; return NULL; } // someone is reading a value for the cam(focalDistance) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFocalDistance(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float focalDistance; focalDistance = [[(WWTCLVarTrace *)clientData datum] focalDistance]; sprintf(buf, "%f", focalDistance); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - setFrameNumber:(int)aFrameNumber { char buf[128]; if ((aFrameNumber <= [self endFrame]) && ([self frameNumber] != aFrameNumber)) //it's valid and it's new { // if it's actually a new frame, we need to flip the "evaluateInterpProc" // flag, so that the next time we render, we run the camera interpolation routine... evaluateInterpProc = YES; } // we assume that the [super setFrameNumber:] clamps to endFrameNumber [super setFrameNumber:aFrameNumber]; // by setting the frame number, we need to make sure that all the // appropriate other parts of the camera have been updated. What // automatically follows along? Well, the shutterOpenTime needs to get // updated, at least... [self setShutterOpenTime:(shotStartTime + (frameNumber * frameTimeIncrement))]; sprintf(buf, "%d", frameNumber); [tclInterp setVar2:"cam" :"frameNumber" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } - resetFrameNumber { [self setFrameNumber:0]; return self; } // someone is writing a new value for the cam(frameNumber) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForFrameNumber(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; int frameNumber = 1; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; // frameNumber has to be an integer sscanf(varString, "%d", &frameNumber); [[(WWTCLVarTrace *)clientData datum] setFrameNumber:frameNumber]; return NULL; } // someone is reading a value for the cam(frameNumber) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFrameNumber(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; int frameNumber; frameNumber = [[(WWTCLVarTrace *)clientData datum] frameNumber]; sprintf(buf, "%d", frameNumber); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } // whenever the frame number or the frameTimeIncrement gets changed, // the open and close time need to be recalculated - (RtFloat)shutterOpenTime { return shutterOpenTime; } - setShutterOpenTime:(RtFloat)newShutterOpenTime { char buf[128]; shutterOpenTime = newShutterOpenTime; sprintf(buf, "%f", shutterOpenTime); [tclInterp setVar2:"cam" :"shutterOpenTime" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(shutterOpenTime) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForShutterOpenTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; RtFloat shutterOpenTime = 0.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &shutterOpenTime); [[(WWTCLVarTrace *)clientData datum] setShutterOpenTime:shutterOpenTime]; return NULL; } // someone is reading a value for the cam(shutterOpenTime) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForShutterOpenTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; RtFloat shutterOpenTime; shutterOpenTime = [[(WWTCLVarTrace *)clientData datum] shutterOpenTime]; sprintf(buf, "%f", shutterOpenTime); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (RtFloat)shutterCloseTime { if (shooting) { return (shutterOpenTime + (exposureLength * exposureLengthFactor)); } // it's a still frame; no need to modulate the exposure length... return (shutterOpenTime + exposureLength); } // someone is writing a new value for the cam(shutterCloseTime) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForShutterCloseTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { return "cam(shutterCloseTime) is read-only"; } // someone is reading a value for the cam(shutterCloseTime) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForShutterCloseTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; RtFloat shutterCloseTime; shutterCloseTime = [[(WWTCLVarTrace *)clientData datum] shutterCloseTime]; sprintf(buf, "%f", shutterCloseTime); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (float)frameTimeIncrement { return frameTimeIncrement; } - (float)exposureLength { return exposureLength; } - setExposureLength:(float)newExposureLength { char buf[128]; // need to make sure that the new exposure length is consistent with the rest of the camera // what does this mean? // the length of the exposure cannot be longer than the interval between frames, i.e. // exposureLength <= (frameTimeIncrement == 1./framesPerSecond) // //NXLogError("newExposureLength == %f\n", newExposureLength); if (newExposureLength < 0.0) { NXLogError("exposureLength must be a positive number, not %f\n", newExposureLength); return nil; } // actually, we only want to do this if we're shooting. Anyway, at // the start of shooting a shot (i.e. an ordered sequence), we should // sanity check then - this might be perfectly reasonable for a still // frame... if (shooting) { if (newExposureLength > [self frameTimeIncrement]) { exposureLength = [self frameTimeIncrement]; } else { exposureLength = newExposureLength; } } else // don't do a clip; it could be whatever positive value they want... { exposureLength = newExposureLength; } sprintf(buf, "%f", exposureLength); [tclInterp setVar2:"cam" :"exposureLength" toValue:buf]; [delegate cameraParametersWereUpdated:self]; justResetExposureLength = YES; return self; } // someone is writing a new value for the cam(exposureLength) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForExposureLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; RtFloat exposureLength = 0.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; sscanf(varString, "%f", &exposureLength); [[(WWTCLVarTrace *)clientData datum] setExposureLength:exposureLength]; return NULL; } // someone is reading a value for the cam(exposureLength) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForExposureLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; RtFloat exposureLength; exposureLength = [[(WWTCLVarTrace *)clientData datum] exposureLength]; sprintf(buf, "%f", exposureLength); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (float)framesPerSecond { return framesPerSecond; } - setFramesPerSecond:(float)newFramesPerSecond { char buf[128]; RtFloat maxExposureLength; int newEndFrame; // okay, the frames/second is being changed. // what do we need to update? // we want the duration of the shot (in seconds) to stay the same, // so we need to: // - make sure that the exposureLength is still valid; if not, clamp it // - reset the startFrame to 0 and the endFrame to whatever is appropriate framesPerSecond = newFramesPerSecond; sprintf(buf, "%f", newFramesPerSecond); [tclInterp setVar2:"cam" :"FramesPerSecond" toValue:buf]; frameTimeIncrement = (1.0/framesPerSecond); maxExposureLength = frameTimeIncrement; // if, by changing the frame rate, we've invalidated the current // setting for how long the shutter stays open for each frame, we need to // reset it to a valid value. If it's still valid, leave it be (i.e. if // it was a strobe camera, it will stay that way). // uh, no. There are two normal cases: keep the exposureLength at 0.0, for a strobe, // or keep the exposureLength == frameTimeIncrement. So... if they want a special // setting, they'll need to reset it after setting a new fps. // uh, no I changed my mind again. If they want a *strobe*, they have to reset it explicitly // this is what I want in most cases (i.e. I want motion blur) [self setExposureLength:maxExposureLength]; newEndFrame = (framesPerSecond * [self shotLength]); // actually should do the right thing at the half frame mark... [super setStartFrame:0 endFrame:newEndFrame incrementFramesBy:[self frameIncrement]]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(framesPerSecond) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForFramesPerSecond(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float framesPerSecond = 17.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; // framesPerSecond has to be a float sscanf(varString, "%f", &framesPerSecond); [[(WWTCLVarTrace *)clientData datum] setFramesPerSecond:framesPerSecond]; return NULL; } // someone is reading a value for the cam(framesPerSecond) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForFramesPerSecond(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float framesPerSecond; framesPerSecond = [[(WWTCLVarTrace *)clientData datum] framesPerSecond]; sprintf(buf, "%f", framesPerSecond); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (float)shotLength { return shotLength; } - setShotLength:(float)newShotLength { char buf[128]; int newEndFrame; // okay, the frames/second is being changed. // what do we need to update? // - reset the startFrame to 0 and the endFrame to whatever is appropriate shotLength = newShotLength; sprintf(buf, "%f", newShotLength); [tclInterp setVar2:"cam" :"shotLength" toValue:buf]; newEndFrame = (shotLength * [self framesPerSecond]) - 1; // actually should the right thing at the half frame mark... [super setStartFrame:0 endFrame:newEndFrame incrementFramesBy:[self frameIncrement]]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(shotLength) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForShotLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float shotLength = 17.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; // ShotLength has to be a float sscanf(varString, "%f", &shotLength); [[(WWTCLVarTrace *)clientData datum] setShotLength:shotLength]; return NULL; } // someone is reading a value for the cam(ShotLength) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForShotLength(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float shotLength; shotLength = [[(WWTCLVarTrace *)clientData datum] shotLength]; sprintf(buf, "%f", shotLength); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (float)shotStartTime { return shotStartTime; } - setShotStartTime:(float)newShotStartTime { char buf[128]; shotStartTime = newShotStartTime; sprintf(buf, "%f", newShotStartTime); [tclInterp setVar2:"cam" :"shotStartTime" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(shotStartTime) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForShotStartTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float shotStartTime = 0.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; // ShotStartTime has to be a float sscanf(varString, "%f", &shotStartTime); [[(WWTCLVarTrace *)clientData datum] setShotStartTime:shotStartTime]; return NULL; } // someone is reading a value for the cam(shotStartTime) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForShotStartTime(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float shotStartTime; shotStartTime = [[(WWTCLVarTrace *)clientData datum] shotStartTime]; sprintf(buf, "%f", shotStartTime); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (float)exposureLengthFactor { return exposureLengthFactor; } - setExposureLengthFactor:(float)newExposureLengthFactor { char buf[128]; exposureLengthFactor = newExposureLengthFactor; // bound it inclusively between 0 and 1 if (exposureLengthFactor < 0.0) { exposureLengthFactor = 0.0; } if (exposureLengthFactor > 1.0) { exposureLengthFactor = 1.0; } sprintf(buf, "%f", newExposureLengthFactor); [tclInterp setVar2:"cam" :"exposureLengthFactor" toValue:buf]; [delegate cameraParametersWereUpdated:self]; return self; } // someone is writing a new value for the cam(exposureLengthFactor) parameter, so we need // to update the WW3DCamera to reflect that new value... char *WriteProcForExposureLengthFactor(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char *varString; float exposureLengthFactor = 0.0; varString = [[(WWTCLVarTrace *)clientData tclInterp] getVar2:name1 :name2]; // exposureLengthFactor has to be a float sscanf(varString, "%f", &exposureLengthFactor); [[(WWTCLVarTrace *)clientData datum] setExposureLengthFactor:exposureLengthFactor]; return NULL; } // someone is reading a value for the cam(exposureLengthFactor) parameter, so we need // to " read-through" the WW3DCamera to reflect the current value... char *ReadProcForExposureLengthFactor(ClientData clientData, Tcl_Interp *interp, char *name1, char *name2, int flags) { char buf[128]; float exposureLengthFactor; exposureLengthFactor = [[(WWTCLVarTrace *)clientData datum] exposureLengthFactor]; sprintf(buf, "%f", exposureLengthFactor); [[(WWTCLVarTrace *)clientData tclInterp] setVar2:name1 :name2 toValue:buf]; return NULL; } - (BOOL)shooting { return shooting; } - setShooting:(BOOL)newShooting { if (shooting && !newShooting) { justFinishedShooting = YES; } shooting = newShooting; return self; } - takeShooting:sender { [self setShooting:(BOOL)[sender intValue]]; return self; } // in this routine, the tcl interp is assumed to have the correct values, and so the camera has to conform to it... // cam(fieldOfView) : fieldOfView : float -> float // cam(eyePoint) : eyePoint : RtPoint -> {x y z} // cam(viewPoint) : viewPoint : RtPoint -> {x y z} // cam(rollAngle) : rollAngle : float -> float // cam(fStop) : fStop : float -> float // cam(focalLength) : focalLength : float -> float // cam(focalDistance) : focalDistance : float -> float // cam(frameNumber) : frameNumber : int -> int // cam(tesselation) // cam(lowRezTesselation) // cam(renderStyle) : // cam(movingRenderStyle) : // NOT DONE YET! // cam(pixelAspectRatio) : pixelAspectRatio : float -> float // cam(projectionType) : projectionType : N3DProjectionType -> string // cam(backgroundColor) : backgroundColor : NXColor -> {r g b} // cam(doesDrawBackgroundColor) : doesDrawBackgroundColor : BOOL -> int // cam(nearPlane) : nearPlane : float -> float // cam(farPlane) : farPlane : float -> float // need to talk about interdependencies of these variables... // send mail to Dan at Pixar and ask, especially about fStop, focalLength, and focalDistance... - setupTraces { char *valAsString, *varName; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; valAsString = (char *)NXZoneCalloc([self zone], 256, sizeof(char)); varName = (char *)NXZoneCalloc([self zone], 256, sizeof(char)); // need to pull out my current camera parameters and send them as // "set cam(paramName) paramValue" to my interp here... // and then we need to set up read and write traces so that any set calls // on any cam() variable will be in synch with this instance... // you may be asking yourself here: "why is wave, that bozo, copying // the strings that correspond to the variables names into a tmp // variable? Is he really that wasteful, just because he has bigger // and more expensive equipment than I do? Is he intentionally wasting // my precious time?" Well, sports fans, no. The problem is that // the current (7.3) implementation of tcl still uses a performance // hack that gets bit by compilers being smart. The short answer is // if you hand tcl a const char* that the compiler has squirreled away // somewhere in read-only space, you will dump core, because tcl, // while doing a comparison on array elements, attempts to stick a '\0' // where the '(' is so it can do a fast hash table lookup. It's very // good about taking the '\0' out once its done, but unfortunately, // you'll never get the chance... This is reasonably well documented // in the tcl doc, and given the efficiency, I can't really complain, // but it *is* a bug (whether in C, the compiler, or tcl, you make the call). // Anyway, to get around it, you either use the setVar2 version, or // you make sure that the string you hand into setVar is writable. // gak... // strcpy(varName, "cam(renderStyle)"); strcpy(varName, "SmoothSolids"); // do a default if ([self renderStyle] == N3D_PointCloud) { strcpy(valAsString, "PointCloud"); } if (renderStyle == N3D_WireFrame) { strcpy(valAsString, "WireFrame"); } if (renderStyle == N3D_ShadedWireFrame) { strcpy(valAsString, "ShadedWireFrame"); } if (renderStyle == N3D_FacetedSolids) { strcpy(valAsString, "FacetedSolids"); } if (renderStyle == N3D_SmoothSolids) { strcpy(valAsString, "SmoothSolids"); } [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForRenderStyle usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForRenderStyle usingData:(ClientData)self]; // strcpy(varName, "cam(movingRenderStyle)"); strcpy(varName, "FacetedSolids"); // do a default if ([self movingRenderStyle] == N3D_PointCloud) { strcpy(valAsString, "PointCloud"); } if (movingRenderStyle == N3D_WireFrame) { strcpy(valAsString, "WireFrame"); } if (movingRenderStyle == N3D_ShadedWireFrame) { strcpy(valAsString, "ShadedWireFrame"); } if (movingRenderStyle == N3D_FacetedSolids) { strcpy(valAsString, "FacetedSolids"); } if (movingRenderStyle == N3D_SmoothSolids) { strcpy(valAsString, "SmoothSolids"); } [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForMovingRenderStyle usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForMovingRenderStyle usingData:(ClientData)self]; // strcpy(varName, "cam(tesselation)"); sprintf(valAsString, "%f", [self tesselation]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForTesselation usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForTesselation usingData:(ClientData)self]; // strcpy(varName, "cam(lowRezTesselation)"); sprintf(valAsString, "%f", [self lowRezTesselation]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForLowRezTesselation usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForLowRezTesselation usingData:(ClientData)self]; // strcpy(varName, "cam(fieldOfView)"); sprintf(valAsString, "%f", [self fieldOfView]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFieldOfViewByAngle usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFieldOfViewByAngle usingData:(ClientData)self]; // [self getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; strcpy(varName, "cam(eyePoint)"); sprintf(valAsString, "%f %f %f", N3D_XComp(anEyePoint), N3D_YComp(anEyePoint), N3D_ZComp(anEyePoint)); [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForEyePoint usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForEyePoint usingData:(ClientData)self]; strcpy(varName, "cam(viewPoint)"); sprintf(valAsString, "%f %f %f", N3D_XComp(aViewPoint), N3D_YComp(aViewPoint), N3D_ZComp(aViewPoint)); [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForViewPoint usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForViewPoint usingData:(ClientData)self]; strcpy(varName, "cam(rollAngle)"); sprintf(valAsString, "%f", aRollAngle); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForRollAngle usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForRollAngle usingData:(ClientData)self]; // strcpy(varName, "cam(fStop)"); sprintf(valAsString, "%f", [self fStop]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFStop usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFStop usingData:(ClientData)self]; // strcpy(varName, "cam(focalLength)"); sprintf(valAsString, "%f", [self focalLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFocalLength usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFocalLength usingData:(ClientData)self]; // strcpy(varName, "cam(focalDistance)"); sprintf(valAsString, "%f", [self focalDistance]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFocalDistance usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFocalDistance usingData:(ClientData)self]; // strcpy(varName, "cam(frameNumber)"); sprintf(valAsString, "%d", [self frameNumber]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFrameNumber usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFrameNumber usingData:(ClientData)self]; // strcpy(varName, "cam(shotLength)"); sprintf(valAsString, "%f", [self shotLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForShotLength usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForShotLength usingData:(ClientData)self]; // strcpy(varName, "cam(shotStartTime)"); sprintf(valAsString, "%f", [self shotStartTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForShotStartTime usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForShotStartTime usingData:(ClientData)self]; // strcpy(varName, "cam(framesPerSecond)"); sprintf(valAsString, "%f", [self framesPerSecond]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForFramesPerSecond usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForFramesPerSecond usingData:(ClientData)self]; // strcpy(varName, "cam(exposureLengthFactor)"); sprintf(valAsString, "%f", [self exposureLengthFactor]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForExposureLengthFactor usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForExposureLengthFactor usingData:(ClientData)self]; // strcpy(varName, "cam(shutterOpenTime)"); sprintf(valAsString, "%f", [self shutterOpenTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForShutterOpenTime usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForShutterOpenTime usingData:(ClientData)self]; // strcpy(varName, "cam(shutterCloseTime)"); sprintf(valAsString, "%f", [self shutterCloseTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForShutterCloseTime usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForShutterCloseTime usingData:(ClientData)self]; // strcpy(varName, "cam(exposureLength)"); sprintf(valAsString, "%f", [self exposureLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForExposureLength usingData:(ClientData)self]; [tclInterp traceReadsOn:varName andCall:(Tcl_VarTraceProc *)ReadProcForExposureLength usingData:(ClientData)self]; // // strcpy(varName, "cam(interpolationProc)"); // need to set up a default interpolation proc... sprintf(valAsString, "noop"); [tclInterp setVar:varName toValue:valAsString]; [tclInterp traceWritesOn:varName andCall:(Tcl_VarTraceProc *)WriteProcForInterpolationProc usingData:(ClientData)self]; // continue for all variables... inSynchWithTclInterp = YES; NXZoneFree([self zone], valAsString); NXZoneFree([self zone], varName); return self; } - initFrame:(const NXRect *)r { RtPoint fromP = {0,0,-5.0}, toP = {0,0,0}; id aShape; [super initFrame:r]; // speed stuff up and help workaround HP 3.2 bug (32 bit w/qrman crashes WS) [self setOpaque:YES]; tclInterp = [[WWInterp alloc] init]; [self initInterp]; renderStyle = N3D_SmoothSolids; movingRenderStyle = N3D_FacetedSolids; scaleUpFactor = 1.05; scaleDownFactor = 0.95; translateXFactor = 0.01; translateYFactor = 0.01; translateZFactor = 0.05; epsilon = 4.0; selectionWidthEpsilon = 8.0; selectionHeightEpsilon = 8.0; shadingRate = 4.0; renderAtMediumRate = 1; renderAtHighRate = 2; renderCheckTimeSlice = 3.0; showSelectedShape = YES; drawOriginForSelectedShape = NO; useRendribInstead = NO; binaryRIB = NO; // setup 3D camera stuff [self setEyeAt:fromP toward:toP roll:0.0]; [self setupDefaultLights]; otherLightList = [[List alloc] init]; // setup some initial global rendering state [self setSurfaceTypeForAll:renderStyle chooseHider:YES]; lowRezTesselationVector[0] = lowRezTesselationVector[1] = 16.0; tesselationVector[0] = tesselationVector[1] = 32.0; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); // stick in a reasonable shader theShader=[[WW3DShader alloc] init]; [theShader setUseColor:YES]; [theShader setColor:ribColor]; [(N3DShader *)theShader setShader:"plastic"]; // stick in a reasonable reference shape aShape = [[WW3DShape alloc] init]; [aShape setShapeName:NXCopyStringBuffer("defaultTorus")]; [aShape setShapeName:NXCopyStringBuffer("WW3DWell")]; [aShape appendRIBCommand:[[RIBColor alloc] init]]; //[aShape appendRIBCommand:[[RIBTorus alloc] init]]; // To show off the RIBCommand archiving bug, uncomment the next // command, recompile, load up the WW3DPalette in IB (running IB in gdb), // and drag the well off the palette... [aShape appendRIBCommand:[[WW3DText alloc] initWithCharPath:"WW3DWell" usingFont:[Font newFont:"Helvetica" size:36] myShape:aShape justification:NX_CENTERED]]; [aShape calculateBoundingBoxStartingAt:0.0 endingAt:0.0]; [aShape setShader_:theShader]; [[self setWorldShape:aShape] free]; // free the default world shape currentShape = nil; [self setCurrentShape:[self worldShape]]; // set current shape to be top [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES]; theRotator = [[N3DRotator alloc] initWithCamera:self]; [theRotator setRotationAxis:N3D_AllAxes]; [self setPreTransformMatrix:(RtFloat (*)[4])N3DIdentityMatrix]; statusBufSize = 256; statusBuf = (char *)NXZoneCalloc([self zone], statusBufSize, sizeof(char)); fStop = RI_INFINITY; // pinhole camera focalLength = 50; focalDistance = abs((N3D_ZComp(fromP) - N3D_ZComp(toP))); shutterOpenTime = 0.0; framesPerSecond = 15.0; frameTimeIncrement = 1.0/framesPerSecond; // start off with 15 fps //savedExposureLength = exposureLength = frameTimeIncrement; // start off with a motion blurred still camera savedExposureLength = exposureLength = 0.0; // start off with a strobe still camera // start off with a film-like motion picture camera exposureLengthFactor = .5; // shot stuff shotStartTime = 0.0; // begin at the beginning... shotLength = 3.0; // let's start off with a 3 second shot frameNumber = 0; startFrame = 0; endFrame = shotLength * framesPerSecond; [self setShooting:NO]; justFinishedShooting = NO; justResetExposureLength = NO; [self setupTraces]; /* * Direct interaction support. */ updateShape = NO; updateWhenTracking = NO; changeSelectedShape = NO; fontName = NXCopyStringBuffer("Helvetica"); fontSize = 10.0; fontSpacing = 2.0; spacingFactor = -1.0/72.0; tabLength = -20 * spacingFactor; //timeFactor = 1.0/72.0; timeFactor = 3.0; sampleOffset = 10 * timeFactor; runTimeSystem = nil; return self; } // the receptor gets sent this message when the object is dragged into // the File window, and when it is unarchived from the nib file. - awake { [super awake]; // everything else has just been unarchived... [self initInterp]; theRotator = [[N3DRotator alloc] initWithCamera:self]; [theRotator setRotationAxis:N3D_AllAxes]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); currentShape = nil; [self setCurrentShape:[self worldShape]]; // set current shape to be top statusBufSize = 256; statusBuf = (char *)NXZoneCalloc([self zone], statusBufSize, sizeof(char)); frameTimeIncrement = 1.0/framesPerSecond; savedExposureLength = exposureLength; justFinishedShooting = NO; justResetExposureLength = NO; fontName = NXCopyStringBuffer("Helvetica"); fontSize = 10.0; fontSpacing = 2.0; spacingFactor = -1.0/72; tabLength = -20 * spacingFactor; timeFactor = 1.0/72.0; sampleOffset = 10 * timeFactor; [self setupTraces]; // for right now, disable binary rib output until I fix it... binaryRIB = NO; runTimeSystem = nil; return self; } - free { id theInterp; //NXLogError("WW3DCamera %p being free'ed\n", self); if (statusBuf) { /* NXLogError("freeing statusBuf %p\n", statusBuf);*/ NXZoneFree([self zone], statusBuf); } [self removeAnimateTE]; [self removeRenderTE]; if (fontName) { /* NXLogError("freeing fontName %p\n", fontName); */ free(fontName); } // MAKE SURE YOU'VE FREED EVERYTHING EXCEPT worldShape AND tclInterp BY THIS POINT!!!!! // make sure you free the tcl interp after the worldShape, because // EveCommands that get free'd will want to untrace their corresponding // tcl variables, and we don't want them sending messages to an already // free'd tclInterp // This only applies if there *is* a worldShape... if (worldShape) { theInterp = tclInterp; //NXLogError("WW3DCamera %p being free'ed\n", self); [super free]; NXLogError("about to free tclInterp %p (after super)\n", theInterp); [theInterp free]; } else { //NXLogError("about to free tclInterp %p (before super)\n", theInterp); [tclInterp free]; [super free]; } return nil; } - synchToSceneClock:aSceneClock { float sceneTime = [aSceneClock timestamp]; // the idea here is to advance to the first frame that shows the scene's time. [self setFrameNumber:(int)(sceneTime * framesPerSecond)]; [self display]; return self; } - dumpCameraStateTo:(const char *)camName { char *valAsString, *varName; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; valAsString = (char *)NXZoneCalloc([self zone], 256, sizeof(char)); varName = (char *)NXZoneCalloc([self zone], 256, sizeof(char)); // need to pull out my current camera parameters and send them as // "set camName(paramName) paramValue" to my interp here... // and then we need to set up write traces so that any set calls fail // sprintf(varName, "%s(fieldOfView)", camName); sprintf(valAsString, "%f", [self fieldOfView]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // [self getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; sprintf(varName, "%s(eyePoint)", camName); sprintf(valAsString, "%f %f %f", N3D_XComp(anEyePoint), N3D_YComp(anEyePoint), N3D_ZComp(anEyePoint)); [tclInterp setVar:varName toReadOnlyValue:valAsString]; sprintf(varName, "%s(viewPoint)", camName); sprintf(valAsString, "%f %f %f", N3D_XComp(aViewPoint), N3D_YComp(aViewPoint), N3D_ZComp(aViewPoint)); [tclInterp setVar:varName toReadOnlyValue:valAsString]; sprintf(varName, "%s(rollAngle)", camName); sprintf(valAsString, "%f", aRollAngle); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(fStop)", camName); sprintf(valAsString, "%f", [self fStop]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(focalLength)", camName); sprintf(valAsString, "%f", [self focalLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(focalDistance)", camName); sprintf(valAsString, "%f", [self focalDistance]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(frameNumber)", camName); sprintf(valAsString, "%d", [self frameNumber]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(shutterOpenTime)", camName); sprintf(valAsString, "%f", [self shutterOpenTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(shutterCloseTime)", camName); sprintf(valAsString, "%f", [self shutterCloseTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(frameTimeIncrement)", camName); sprintf(valAsString, "%f", [self frameTimeIncrement]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(exposureLength)", camName); sprintf(valAsString, "%f", [self exposureLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // NXZoneFree([self zone], valAsString); NXZoneFree([self zone], varName); return self; } - restoreCameraStateFrom:(const char *)camName { char *valAsString = NULL, *varName; RtPoint anEyePoint, aViewPoint; RtFloat aRollAngle; varName = (char *)NXZoneCalloc([self zone], 256, sizeof(char)); // need to pull out my current camera parameters and send them as // "set camName(paramName) paramValue" to my interp here... // and then we need to set up write traces so that any set calls fail // sprintf(varName, "%s(fieldOfView)", camName); valAsString = [tclInterp getVar:varName]; [self setFieldOfViewByAngle:(float)atof(valAsString)]; // should I free valAsString here? // [self getEyeAt:&anEyePoint toward:&aViewPoint roll:&aRollAngle]; sprintf(varName, "%s(eyePoint)", camName); sprintf(valAsString, "%f %f %f", N3D_XComp(anEyePoint), N3D_YComp(anEyePoint), N3D_ZComp(anEyePoint)); [tclInterp setVar:varName toReadOnlyValue:valAsString]; sprintf(varName, "%s(viewPoint)", camName); sprintf(valAsString, "%f %f %f", N3D_XComp(aViewPoint), N3D_YComp(aViewPoint), N3D_ZComp(aViewPoint)); [tclInterp setVar:varName toReadOnlyValue:valAsString]; sprintf(varName, "%s(rollAngle)", camName); sprintf(valAsString, "%f", aRollAngle); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(fStop)", camName); sprintf(valAsString, "%f", [self fStop]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(focalLength)", camName); sprintf(valAsString, "%f", [self focalLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(focalDistance)", camName); sprintf(valAsString, "%f", [self focalDistance]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(frameNumber)", camName); sprintf(valAsString, "%d", [self frameNumber]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(shutterOpenTime)", camName); sprintf(valAsString, "%f", [self shutterOpenTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(shutterCloseTime)", camName); sprintf(valAsString, "%f", [self shutterCloseTime]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(frameTimeIncrement)", camName); sprintf(valAsString, "%f", [self frameTimeIncrement]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // sprintf(varName, "%s(exposureLength)", camName); sprintf(valAsString, "%f", [self exposureLength]); // turn the value into its tcl equivalent [tclInterp setVar:varName toReadOnlyValue:valAsString]; // NXZoneFree([self zone], valAsString); NXZoneFree([self zone], varName); return self; } - evaluateCameraInterpolationRoutineWith:(float)u { char cmd[80]; sprintf(cmd, "eval $cam(interpolationProc) %f", u); //NXLogError("WW3DCamera's interp evaluating camera interpolation routine with %f for frame number %d here...\n", // u, [self frameNumber]); [tclInterp globalEval:cmd]; return self; } - renderMapsToStream:(NXStream *)ns { [worldShape renderMaps:self usingStream:ns]; return self; } - renderMaps { [worldShape renderMaps:self]; return self; } - worldBegin:(RtToken)context { RtInt jitterFlag = 1; float u; int theFrameNumber; static char *offPtr = "off"; static int patchMaxLevel = 4.0; if (dumpingToRIB) { //static RtInt v31 = 301; //RiOption(RI_ARCHIVE, "outputversion", &v31, RI_NULL); [self renderMaps]; } if (useRendribInstead) { RiArchiveRecord(RI_COMMENT, "the following declare all the non-standard variables for rendrib"); RiArchiveRecord(RI_COMMENT, "rendrib declares these internally, but prman or WavesWorld would complain if"); RiArchiveRecord(RI_COMMENT, "it got passed a RIB file with these attributes if they hadn't been declared"); RiDeclare("include", "uniform string"); RiDeclare("shadows", "uniform string"); RiDeclare("verbosity", "uniform string"); RiDeclare("casts_shadows", "uniform string"); RiDeclare("zonal", "uniform string"); RiDeclare("patchsize", "uniform float"); RiDeclare("elemsize", "uniform float"); RiDeclare("minsize", "uniform float"); RiDeclare("displacement", "uniform float"); RiDeclare("patch_maxlevel", "uniform integer"); RiDeclare("max_raylevel", "uniform integer"); RiDeclare("minshadowbias", "uniform float"); RiDeclare("minsamples", "uniform integer"); RiDeclare("maxsamples", "uniform integer"); RiDeclare("branch_ratio", "uniform integer"); RiDeclare("max_branch_ratio", "uniform integer"); RiDeclare("binary", "uniform integer"); RiDeclare("averagecolor", "uniform color"); RiDeclare("emissioncolor", "uniform color"); RiArchiveRecord(RI_COMMENT, "the following turns off shadows as the default for this file when using rendrib"); RiAttribute("light", "shadows", &offPtr, RI_NULL); } else { RiArchiveRecord(RI_COMMENT, "a shader included in prman 3.4 used to ensure color doesn't exceed alpha"); RiImager("clamptoalpha", RI_NULL); } // okay, if the shading rate is less than 1, use PixelSamples 3 3 // okay, if the shading rate is greater than or equal to 1 but less than 4, use PixelSamples 2 2 // okay, if the shading rate is greater than or equal to 4, use PixelSamples 1 1 if ((shadingRate < 1.0) && (exposureLength > 0.0)) { if (useRendribInstead) { RiArchiveRecord(RI_COMMENT, "the following stops patch subdivision at level 8 when using rendrib. If your geometry looks blocky, make the value bigger"); patchMaxLevel = 8; RiAttribute("render", "patch_maxlevel", &patchMaxLevel, RI_NULL); RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 3 3 because you're using such a high quality shading rate"); RiArchiveRecord(RI_COMMENT, "and there is potentially motion blur in this frame."); RiArchiveRecord(RI_COMMENT, "Since you're probably using rendrib, though, the ShadingRate is ignored, but things will render faster if the PixelSamples was lower."); } else { RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 3 3 because you're using such a high quality shading rate."); RiArchiveRecord(RI_COMMENT, "Assuming you're using prman, things will render faster if this number was lower, or the ShadingRate value was higher."); } RiPixelSamples(3.0, 3.0); } else { if (shadingRate < 4.0) { if (useRendribInstead) { RiArchiveRecord(RI_COMMENT, "the following stops patch subdivision at level 4 when using rendrib. If your geometry looks blocky, make the value bigger"); patchMaxLevel = 4; RiAttribute("render", "patch_maxlevel", &patchMaxLevel, RI_NULL); RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 2 2 because you're using a reasonable quality shading rate."); RiArchiveRecord(RI_COMMENT, "Since you're probably using rendrib, though, the ShadingRate is ignored, but things will render faster if the PixelSamples was lower."); } else { RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 2 2 because you're using a reasonable quality shading rate."); RiArchiveRecord(RI_COMMENT, "Assuming you're using prman, things will render faster if this number was lower, or the ShadingRate value was higher."); } RiPixelSamples(2.0, 2.0); } else { if (useRendribInstead) { RiArchiveRecord(RI_COMMENT, "the following stops patch subdivision at level 2 when using rendrib. If your geometry looks blocky, make the value bigger"); patchMaxLevel = 2; RiAttribute("render", "patch_maxlevel", &patchMaxLevel, RI_NULL); RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 1 1 because you're using a low quality shading rate."); RiArchiveRecord(RI_COMMENT, "Since you're probably using rendrib, though, the ShadingRate is ignored, but things will look better if the PixelSamples was higher."); } else { RiArchiveRecord(RI_COMMENT, "please note: I'm purposely setting the PixelSamples to 1 1 because you're using a low quality shading rate."); RiArchiveRecord(RI_COMMENT, "Assuming you're using prman, things will look better if this number was higher, or the ShadingRate value was lower."); } RiPixelSamples(1.0, 1.0); } } // Run camera interpolation procedure here. We do it here (as opposed // to doing it in drawSelf:), because at this point, all the camera // parameters are as fixed as they're gonna get for this frame. // when a new frame number is set with setFrameNumber:, it sets the // BOOL evaluateInterpProc. We only want to run this proc once per // frame, but we also don't want to do it until this point. So... // at this point, if the flag is set, we evaluate the proc with // the current value of u. // note that if the currentFrame == startFrame, and the flag is set, // we need to do some initial work to set up the state. We need to // fill out the global tcl array startCam(), which is to have the state // of the current camera in read-only variables... if (shooting) { theFrameNumber = [self frameNumber]; if (theFrameNumber == 0) // sanity check! { savedExposureLength = exposureLength; [self setExposureLength:([self frameTimeIncrement] * exposureLengthFactor)]; } if (evaluateInterpProc) { if (theFrameNumber == 0) { // initialize startCam() array with my current state [tclInterp unsetVar:"startCam"]; [self dumpCameraStateTo:"startCam"]; u = 0; } else { // calculate u, where u is 0 at startFrame and 1 at endFrame // let's say startFrame is 0, endFrame is 100, and frameNumber is 25 // we want u to be .25 // note that we should not have to worry about div by zero here... u = (float)theFrameNumber/(float)([self endFrame] - 1); } [self evaluateCameraInterpolationRoutineWith:u]; evaluateInterpProc = NO; } } else // if we're not shooting, we want the camera to be in synch with the scene clock and be a strobe camera... { // ask the sceneClock what time it is, and make ourselves a strobe camera if (justFinishedShooting) // when we come out of a shot, reset the exposureLength to what it was previously { [self setExposureLength:savedExposureLength]; // need to do it "correctly", so tcl is notified justFinishedShooting = NO; } [self setShutterOpenTime:[sceneClock timestamp]]; // need to do it "correctly", so tcl is notified } // If I want to support depth-of-field, need to call RiDepthOfField() RiDepthOfField(fStop, focalLength, focalDistance); // If I want to support motion blur, need to call RiShutter(), as well // as having RiMotionBegin/End blocks around primitives if (shooting) { RiShutter(shutterOpenTime, (shutterOpenTime + (exposureLength * exposureLengthFactor))); } else { RiShutter(shutterOpenTime, (shutterOpenTime + exposureLength)); } if (exposureLength > 0.0) // is it a strobe or not? { // optimize for motion blur... // really should find out what the hider has been set to... RiHider("hidden", "jitter", &jitterFlag, RI_NULL); } // or whatever the heck is the right thang... if (renderCount == renderAtMediumRate) { RiShadingRate(50.0); } else { if (renderCount == renderAtHighRate) { RiShadingRate(5.0); } } [super worldBegin:context]; return self; } - getTransformMatrix:(RtMatrix)aMatrix { N3D_CopyMatrix(transform, aMatrix); return self; } - takeStatusText:sender { statusText = sender; return self; } - delegate { return delegate; } /////////////////////// // 3D stuff /////////////////////// - setNoCurrentShape:sender { currentShape = nil; return self; } - currentShape { return currentShape; } - setCurrentShape:newCurrentShape { // should make sure newShape is a child of worldShape... [currentShape setSelected:NO andDrawOrigin:NO]; [worldShape setDrawAsBox:drawWorldAsBox]; if (drawCurrentAsBox) { [currentShape setDrawAsBox:NO]; } currentShape = newCurrentShape; [currentShape setSelected:showSelectedShape andDrawOrigin:drawOriginForSelectedShape]; if (drawCurrentAsBox) { [currentShape setDrawAsBox:YES]; } // WAVE this is expensive; I should have a flag... //[self display]; if (statusText) // potentially record activity { sprintf(statusBuf, "currentShape is: %s", [currentShape shapeName]); [statusText setStringValue:statusBuf]; } return self; } - (RtFloat)tesselation { return tesselationVector[0]; } - setTesselation:(RtFloat)newValue { tesselationVector[0] = tesselationVector[1] = newValue; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); return self; } - takeTesselation:sender { tesselationVector[0] = tesselationVector[1] = [sender floatValue]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); if (statusText) // potentially record activity { sprintf(statusBuf, "tesselation set to (%f %f)", tesselationVector[0], tesselationVector[1]); [statusText setStringValue:statusBuf]; } [self display]; return self; } - (RtFloat)lowRezTesselation { return lowRezTesselationVector[0]; } - setLowRezTesselation:(RtFloat)newValue { lowRezTesselationVector[0] = lowRezTesselationVector[1] = newValue; return self; } - takeLowRezTesselation:sender { lowRezTesselationVector[0] = lowRezTesselationVector[1] = [sender floatValue]; if (statusText) // potentially record activity { sprintf(statusBuf, "low rez tesselation set to (%f %f)", lowRezTesselationVector[0], lowRezTesselationVector[1]); [statusText setStringValue:statusBuf]; } return self; } - (float)shadingRate { return shadingRate; } - takeShadingRate:sender { shadingRate = [sender floatValue]; if (shadingRate < 0.25) { shadingRate = 0.25; } if (shadingRate > 100.0) { shadingRate = 100.0; } return self; } - takeAmbientLightState:sender { [ambientLight switchLight:[sender intValue]]; return [self display]; } - takeAmbientLightIntensity:sender { [ambientLight setIntensity:[sender floatValue]]; return [self display]; } - takeAmbientLightColor:sender { [ambientLight setColor:[sender color]]; return [self display]; } - takeLeftLightState:sender { [leftLight switchLight:[sender intValue]]; return [self display]; } - takeLeftLightIntensity:sender { [leftLight setIntensity:[sender floatValue]]; return [self display]; } - takeLeftLightColor:sender { [leftLight setColor:[sender color]]; return [self display]; } - takeRightLightState:sender { [rightLight switchLight:[sender intValue]]; return [self display]; } - takeRightLightIntensity:sender { [rightLight setIntensity:[sender floatValue]]; return [self display]; } - takeRightLightColor:sender { [rightLight setColor:[sender color]]; return [self display]; } - (BOOL)ambientLightState { return [ambientLight on]; } - (RtFloat)ambientLightIntensity { return [ambientLight intensity]; } - (NXColor)ambientLightColor { return [ambientLight color]; } - (BOOL)leftLightState { return [leftLight on]; } - (RtFloat)leftLightIntensity { return [leftLight intensity]; } - (NXColor)leftLightColor { return [leftLight color]; } - (BOOL)rightLightState { return [rightLight on]; } - (RtFloat)rightLightIntensity { return [ rightLight intensity]; } - (NXColor)rightLightColor { return [rightLight color]; } - saveImage:sender { static id savePanel=nil; NXStream *ts; if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"tiff"]; if([savePanel runModal]) { ts = NXOpenMemory(NULL, 0, NX_READWRITE); [image writeTIFF:ts allRepresentations:NO usingCompression:NX_TIFF_COMPRESSION_LZW andFactor:1.0]; NXSaveToFile(ts, [savePanel filename]); NXCloseMemory(ts,NX_FREEBUFFER); } return self; } - dumpRIB:sender { static id savePanel=nil; NXStream *ts; char filename[MAXPATHLEN+1]; char *ascii = "ascii", *binary = "binary"; dumpingToRIB = YES; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping RIB..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"rib"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); // remove the .rib extension from the path returned by the SavePanel basename([savePanel filename], ".rib", filename); // feed to NXPrintf to put in the custom Display command NXPrintf(ts, "# This RIB file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", filename); NXPrintf(ts, "ShadingRate %f\n", shadingRate); // set the output format: if (binaryRIB) { format = binary; } else { format = ascii; } RiDeclare("format", "uniform string"); RiOption("rib", "format", &format, RI_NULL); // then feed the rib code to the stream and [self copyRIBCode:ts]; // save the stream to the file selected in the savepanel NXSaveToFile(ts, [savePanel filename]); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } dumpingToRIB = NO; return self; } - setRunTimeSystem:newRTS { runTimeSystem = newRTS; return self; } - copyRIBCode:(NXStream *)ts { id retID, tmpText = statusText; sprintf(statusBuf, "disabling status display to avoid NeXT's copyRIBCode: bug..."); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); statusText = nil; [runTimeSystem disableStatusText]; [self renderMapsToStream:ts]; retID = [super copyRIBCode:ts]; statusText = tmpText; [runTimeSystem reenableStatusText]; return retID; } - dumpShotToRIBFile:(const char *)longFilename { NXStream *ts; char filename[MAXPATHLEN+1]; int oldFrameNumber, i, startI, endI, incI; static id savePanel=nil; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping complete shot to RIB file %s...", longFilename); [statusText setStringValue:statusBuf]; } // make sure it's a RIB file (at least 1.rib)... if (longFilename && (strlen(longFilename) > 4) && (!strcmp(".rib", (const char *)(longFilename + strlen(longFilename) - 4)))) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); // remove the .rib extension from the path returned by the SavePanel basename(longFilename, ".rib", filename); // feed to NXPrintf to put in the custom Display command NXPrintf(ts, "# This RIB file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); // we need to loop over the whole shot, starting at the first frame, and incrementing correctly. // The 3DKit will take care of putting in frame numbers, but we need to manage the names of the // tiff files that will get saved out. The WWAnimatable and WWRenderable objects that this camera // is attached to will take care of figuring out what time it is when the camera takes their picture. NXPrintf(ts, "ShadingRate %f\n\n\n", shadingRate); oldFrameNumber = [self frameNumber]; startI = [self startFrame]; endI = [self endFrame]; incI = [self frameIncrement]; // due to a bug in NeXT's 3DKit, we want to make sure that // nothing gets written out to a view while we're in // "copyRIBCode:". Unfortunately, that's pretty hard... The most likely // culprit is a routine (like the current camera's interpolation routine) // writing out to the "statusText" outlet. Probably the best thing to do // then is to save the value of that outlet and set it to nil for the // duration of copyRIBCode:... actually, the better thing to do is // probably reimplement copyRIBCode:, where I unset the outlet, call // the super's version, and then set it back. Yea, let's try that... shooting = YES; [self setFrameNumber:(startI - 1)]; // just to flush state... for (i = startI; i < endI; i += incI) { [self setFrameNumber:i]; NXPrintf(ts, "\n\n"); NXPrintf(ts, "\nDisplay \"%s.%d.tiff\" \"file\" \"rgba\"\n", filename, i); [self copyRIBCode:ts]; } NXSaveToFile(ts, [savePanel filename]); NXCloseMemory(ts,NX_FREEBUFFER); [self setFrameNumber:oldFrameNumber]; shooting = NO; } else { sprintf(statusBuf, "<%s> is not a valid filename for a RIB file.\n", longFilename); [statusText setStringValue:statusBuf]; return nil; } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - dumpShotToRIB:sender { static id savePanel=nil; NXStream *ts; char filename[MAXPATHLEN+1]; int oldFrameNumber, i, startI, endI, incI; char *ascii = "ascii", *binary = "binary"; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping complete shot to RIB..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"rib"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); // remove the .rib extension from the path returned by the SavePanel basename([savePanel filename], ".rib", filename); // set the output format: if (binaryRIB) { format = binary; } else { format = ascii; } RiDeclare("format", "uniform string"); RiOption("rib", "format", &format, RI_NULL); // feed to NXPrintf to put in the custom Display command NXPrintf(ts, "# This RIB file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); // we need to loop over the whole shot, starting at the first frame, and incrementing correctly. // The 3DKit will take care of putting in frame numbers, but we need to manage the names of the // tiff files that will get saved out. The WWAnimatable and WWRenderable objects that this camera // is attached to will take care of figuring out what time it is when the camera takes their picture. NXPrintf(ts, "ShadingRate %f\n", shadingRate); oldFrameNumber = [self frameNumber]; startI = [self startFrame]; endI = [self endFrame]; incI = [self frameIncrement]; // due to a bug in NeXT's 3DKit, we want to make sure that // nothing gets written out to a view while we're in // "copyRIBCode:". Unfortunately, that's pretty hard... The most likely // culprit is a routine (like the current camera's interpolation routine) // writing out to the "statusText" outlet. Probably the best thing to do // then is to save the value of that outlet and set it to nil for the // duration of copyRIBCode:... actually, the better thing to do is // probably reimplement copyRIBCode:, where I unset the outlet, call // the super's version, and then set it back. Yea, let's try that... shooting = YES; [self setFrameNumber:(startI - 1)]; // just to flush state... // set scene time as we're moving through... [sceneClock setCurrentTimeQuietly:[self shutterOpenTime]]; // god this is gross!! [sceneClock setCurrentTimeQuietly:[self shutterCloseTime]]; // god this is gross!! for (i = startI; i < endI; i += incI) { [self setFrameNumber:i]; // set scene time as we're moving through... [sceneClock setCurrentTimeQuietly:[self shutterOpenTime]]; // god this is gross!! [sceneClock setCurrentTimeQuietly:[self shutterCloseTime]]; // god this is gross!! NXPrintf(ts, "Display \"%s.%d.tiff\" \"file\" \"rgba\"\n", filename, i); [self copyRIBCode:ts]; } NXSaveToFile(ts, [savePanel filename]); NXCloseMemory(ts,NX_FREEBUFFER); [self setFrameNumber:oldFrameNumber]; [sceneClock setCurrentTime:[self shutterOpenTime]]; // god this is gross!! shooting = NO; } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - dumpEve:sender { static id savePanel=nil; NXStream *ts; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping Eve..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"eve"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); // feed to NXPrintf to put in the custom Display command NXPrintf(ts, "# This eve model file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); [[worldShape tclInterp] writeState:ts]; // then tell the worldShape to write itself out, which will recurse down... [worldShape writeEve:ts atTabLevel:0]; // save the stream to the file selected in the savepanel NXSaveToFile(ts, [savePanel filename]); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - dumpScene:sender { static id savePanel=nil; NXStream *ts; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping scene..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"wwScene"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); NXPrintf(ts, "#\n"); NXPrintf(ts, "# This eve scene file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); [[worldShape tclInterp] writeState:ts]; // then tell the worldShape to write itself out, which will recurse down... [worldShape writeScene:ts atTabLevel:0]; // save the stream to the file selected in the savepanel NXSaveToFile(ts, [savePanel filename]); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - dumpInventor:sender { static id savePanel=nil; NXStream *ts; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping SGI Open Inventor 2.0 file..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"iv"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); NXPrintf(ts, "#Inventor V2.0 ascii\n#\n"); NXPrintf(ts, "# This Inventor file was automatically generated from an eve model file\n"); NXPrintf(ts, "# generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); NXPrintf(ts, "# At the tone, the current time is: %f ... Beep!\n#\n#\n", shutterOpenTime); NXPrintf(ts, "Separator {\n"); NXPrintf(ts, "\t# RenderMan is a left-handed coordinate system, Inventor is right-handed, so this should fix things, right?\n"); NXPrintf(ts, "\tScale {\n"); NXPrintf(ts, "\t\tscaleFactor 1 1 -1\n"); NXPrintf(ts, "\t}\n"); // then tell the worldShape to write itself out, which will recurse down... [worldShape writeInventorAtTime:shutterOpenTime to:ts atTabLevel:1]; NXPrintf(ts, "}\n"); // save the stream to the file selected in the savepanel NXSaveToFile(ts, [savePanel filename]); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - (const char *)fontName { return fontName; } - (float)fontSize { return fontSize; } - (float)fontSpacing { return fontSpacing; } - (float)spacingFactor { return spacingFactor; } - (float)tabLength { return tabLength; } - (float)timeFactor { return timeFactor; } - (float)sampleOffset { return sampleOffset; } - dump3DTextScene:sender { static id savePanel=nil; NXStream *ts; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping 3D Text scene..."); [statusText setStringValue:statusBuf]; } if (!savePanel) { savePanel=[SavePanel new]; } [savePanel setRequiredFileType:"eve"]; if([savePanel runModal]) { // returned w/pathname, open a stream and ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); NXPrintf(ts, "#\n"); NXPrintf(ts, "# This eve 3D text scene file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); [[worldShape tclInterp] writeState:ts]; NXPrintf(ts, "set __text__(fontName) %s\n", [self fontName]); NXPrintf(ts, "set __text__(fontSize) %f\n", [self fontSize]); NXPrintf(ts, "set __text__(spacing) %f\n", [self fontSpacing]); NXPrintf(ts, "set __text__(spacingFactor) %f\n", [self spacingFactor]); NXPrintf(ts, "set __text__(tabLength) %f\n", [self tabLength]); NXPrintf(ts, "set __text__(timeFactor) %f\n", [self timeFactor]); NXPrintf(ts, "set __text__(sampleOffset) %f\n", [self sampleOffset]); // then tell the worldShape to write itself out, which will recurse down... NXPrintf(ts, "startShape TextWorld\n"); [worldShape write3DTextScene:ts atTabLevel:1 index:0 time:0 until:((float)-1)]; NXPrintf(ts, "endShape\n"); // save the stream to the file selected in the savepanel NXSaveToFile(ts, [savePanel filename]); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); } if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } return self; } - turnOffCropWindow { selectionRegion.size.width = 0.0; selectionRegion.size.height = 0.0; return self; } //RtToken fileContext=NULL, solidContext=NULL; //char *archive="archive",*bintype="binaryfile"; //solidContext=[[N3DContextManager new] mainContext]; // GET THE //CURRENT CONTEXT (USED BY THE 3DKit) //fileContext=RiBegin("FileContext","renderer",&archive,"filepath",&ribFile,"format",&asciitype,RI_NULL); //// PUT HERE RenderMan code... //RiContext(fileContext,RI_NULL); RiEnd(); //RiContext(solidContext,RI_NULL); //[[N3DContextManager new] setCurrentContext:solidContext]; - dumpBinaryRIBToFile:(char *)filename usingShadingRate:(float)sRate hider:(char *)hiderName pixelSamples:(float)pixelSampleX :(float)pixelSampleY { NXRect myFrame; char buf[MAXPATHLEN+1]; float cropMinX, cropMinY, cropMaxX, cropMaxY; RtToken fileContext = NULL, wwContext = NULL; char *archive = "archive", *bintype = "binaryfile"; wwContext = [[N3DContextManager new] mainContext]; fileContext = RiBegin("FileContext", "renderer", &archive, "filepath", &filename, "format", &bintype, RI_NULL); // process the file name for a custom display line such that // "prman <<filename>>.rib" will put the resulting image somewhere // predictably useful. strcpy(buf, filename); // remove the .rib extension from the path returned by the SavePanel strrchr(buf,'.')[0]='\0'; // feed to NXPrintf to put in the custom Display command RiArchiveRecord("comment", "This RIB file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP."); RiArchiveRecord("comment", "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); RiArchiveRecord("comment", "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf); RiArchiveRecord("comment", "ShadingRate %f\n", sRate); RiArchiveRecord("comment", "Hider \"%s\"\n", hiderName); RiArchiveRecord("comment", "PixelSamples %f %f\n", pixelSampleX, pixelSampleY); [self getFrame:&myFrame]; if ((selectionRegion.size.width > selectionWidthEpsilon)||(selectionRegion.size.height > selectionHeightEpsilon)) { if (selectionRegion.origin.x < 0.0) { cropMinX = 0.0; } else { cropMinX = selectionRegion.origin.x/myFrame.size.width; } if ((selectionRegion.size.width + selectionRegion.origin.x) > myFrame.size.width) { cropMaxX = 1.0; } else { cropMaxX = (selectionRegion.size.width + selectionRegion.origin.x)/myFrame.size.width; } //////// Y (note Y is flipped) ////////// if (selectionRegion.origin.y < 0.0) { cropMaxY = 1.0; } else { cropMaxY = 1.0 - (selectionRegion.origin.y/myFrame.size.width); } if ((selectionRegion.size.height + selectionRegion.origin.y) > myFrame.size.height) { cropMinY = 0.0; } else { cropMinY = 1.0 - ((selectionRegion.size.height + selectionRegion.origin.y)/myFrame.size.height); } if (cropMinX < 0.0) { cropMinX = 0.0; } if (cropMinY < 0.0) { cropMinY = 0.0; } if (cropMaxX > 1.0) { cropMaxX = 1.0; } if (cropMaxY > 1.0) { cropMaxY = 1.0; } RiCropWindow(cropMinX, cropMaxX, cropMinY, cropMaxY); } // need to dump all my camera state here... // now need to tell my worldShape to render itself... return self; } - dumpRIBToFile:(char *)filename usingShadingRate:(float)sRate hider:(char *)hiderName pixelSamples:(float)pixelSampleX :(float)pixelSampleY { NXStream *ts; NXRect myFrame; char buf[MAXPATHLEN+1]; float cropMinX, cropMinY, cropMaxX, cropMaxY; dumpingToRIB = YES; if (statusText) // potentially record activity { sprintf(statusBuf, "dumping RIB to file %s...", filename); [statusText setStringValue:statusBuf]; } // set the output format: if (binaryRIB) { [self dumpBinaryRIBToFile:filename usingShadingRate:sRate hider:hiderName pixelSamples:pixelSampleX :pixelSampleY]; } else { ts = NXOpenMemory(NULL, 0, NX_WRITEONLY); // process the file name for a custom display line such that // "prman <<filename>>.rib" will put the resulting image somewhere // predictably useful. strcpy(buf, filename); // remove the .rib extension from the path returned by the SavePanel strrchr(buf,'.')[0]='\0'; // feed to NXPrintf to put in the custom Display command NXPrintf(ts, "# This RIB file generated by Michael B. Johnson's WW3DKit software running atop NEXTSTEP.\n"); NXPrintf(ts, "# Contact him at wave@media.mit.edu or (617) 666-4119 for more information.\n#\n"); NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf); NXPrintf(ts, "ShadingRate %f\n", sRate); NXPrintf(ts, "Hider \"%s\"\n", hiderName); NXPrintf(ts, "PixelSamples %f %f\n", pixelSampleX, pixelSampleY); [self getFrame:&myFrame]; if ((selectionRegion.size.width > selectionWidthEpsilon)||(selectionRegion.size.height > selectionHeightEpsilon)) { //NXLogError("\n\nselectionRegion.origin == (%f, %f)\t\tselectionRegion.size == (%f, %f)\n", // selectionRegion.origin.x, selectionRegion.origin.y, // selectionRegion.size.width, selectionRegion.size.height); //NXLogError("myFrame.origin == (%f, %f)\t\tmyFrame.size == (%f, %f)\n", // myFrame.origin.x, myFrame.origin.y, // myFrame.size.width, myFrame.size.height); //////// X ////////// if (selectionRegion.origin.x < 0.0) { cropMinX = 0.0; } else { cropMinX = selectionRegion.origin.x/myFrame.size.width; } if ((selectionRegion.size.width + selectionRegion.origin.x) > myFrame.size.width) { cropMaxX = 1.0; } else { cropMaxX = (selectionRegion.size.width + selectionRegion.origin.x)/myFrame.size.width; } //////// Y (note Y is flipped) ////////// if (selectionRegion.origin.y < 0.0) { cropMaxY = 1.0; } else { cropMaxY = 1.0 - (selectionRegion.origin.y/myFrame.size.width); } if ((selectionRegion.size.height + selectionRegion.origin.y) > myFrame.size.height) { cropMinY = 0.0; } else { cropMinY = 1.0 - ((selectionRegion.size.height + selectionRegion.origin.y)/myFrame.size.height); } //NXLogError("CropWindow %f %f %f %f\n", cropMinX, cropMaxX, cropMinY, cropMaxY); if (cropMinX < 0.0) { cropMinX = 0.0; } if (cropMinY < 0.0) { cropMinY = 0.0; } if (cropMaxX > 1.0) { cropMaxX = 1.0; } if (cropMaxY > 1.0) { cropMaxY = 1.0; } NXPrintf(ts, "CropWindow %f %f %f %f\n", cropMinX, cropMaxX, cropMinY, cropMaxY); } // then feed the rib code to the stream and [self copyRIBCode:ts]; // save the stream to the file selected in the savepanel NXSaveToFile(ts, filename); // and close the stream (which also flushes it), also making sure // that the allocated memory is freed. NXCloseMemory(ts,NX_FREEBUFFER); if (statusText) // potentially record activity { sprintf(statusBuf, "done!"); [statusText setStringValue:statusBuf]; } } dumpingToRIB = NO; return self; } - dumpRIBToFile:(char *)filename { return [self dumpRIBToFile:filename usingShadingRate:shadingRate hider:"hidden" pixelSamples:2 :2]; } // when the well gets resized, I have to catch this and tell // theRotator about it, cause the default doesn't seem to do it (cause it // ain't a subview, natch)... - sizeTo:(NXCoord)deltaWidth :(NXCoord)deltaHeight { NXPoint aPoint; float radius; [super sizeTo:deltaWidth :deltaHeight]; if (deltaWidth > deltaHeight) { radius = deltaHeight / 2.0; } else { radius = deltaWidth / 2.0; } aPoint.x = deltaWidth/2.0; aPoint.y = deltaHeight/2.0; [theRotator setCenter:&aPoint andRadius:radius]; return self; } - setImageFile:(const char *)filename { // It's actually a bad idea to free this image, because it might be shared... // in this case, screw it, cause this has a very specific use... if (filename && *filename) { image = [NXImage findImageNamed:filename]; if (!image) { image = [[NXImage alloc] init]; [image setDataRetained:YES]; if (![image loadFromFile:filename]) { [self setImage:nil]; NXLogError("unable to load image from file <%s>\n", filename); return nil; } } } else { [self setImage:nil]; return nil; } return self; } - setImage:i { //if (image) //{ [image free]; //} image = i; return self; } #define SIZE 1 static float pattern[SIZE] = {2.}; static float offset = 0; - drawPS:(NXRect *)rects :(int)nRects { NXPoint p = {0.0, 0.0}; NXSize s; if ((selectionRegion.size.width > selectionWidthEpsilon)||(selectionRegion.size.height > selectionHeightEpsilon)) { PSsetgray(NX_WHITE); PSsetlinewidth(0.0); PSsetdash(pattern,SIZE, offset); PSrectstroke(selectionRegion.origin.x, selectionRegion.origin.y, selectionRegion.size.width, selectionRegion.size.height); p.x = ((selectionRegion.origin.x) > 0) ? (selectionRegion.origin.x):0; p.y = ((selectionRegion.origin.y) > 0) ? (selectionRegion.origin.y):0; } // there is a bug in 3.2 HP that gets tickled when you have a View // that is 32 bits deep and has qrman drawing into it. Since I don't // *really* use the fact that there is an alpha component to this image // when I composite it in here, I'm going to punt on doing a "source over" // operation, and just copy it into the View. if (image) { //NXSetColor(NX_COLORBLACK); //PSsetalpha(1.0); [image getSize:&s]; PScompositerect(p.x, p.y, s.width, s.height, NX_COPY); // used to be PScompositerect(p.x, p.y, s.width, s.height, NX_SOVER); [image composite:NX_COPY toPoint:&p]; //used to be [image composite:NX_SOVER toPoint:&p]; } return self; } // need to add timed entries if I'm still holding the modifier down // when I exit the inner modal loop. Use the velocity at exit to set the // frequency of the timed entry... // When I reenter the mouseDown loop, I should remove any outstanding timed entries. // when doing a timed entry, I should record frame rate and display it on the status bar - removeAnimateTE { if (animateTE) { DPSRemoveTimedEntry(animateTE); animateTE = 0; animateRotate = NO; // switch back to the N3D_SmoothSolids surface type [self setSurfaceTypeForAll:renderStyle chooseHider:YES]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); } return self; } - animateRotate { [theRotator trackMouseFrom:&oldMouse to:&newMouse rotationMatrix:rmat andInverse:irmat]; [worldShape concatTransformMatrix:rmat premultiply:YES]; oldMouse.x = newMouse.x; oldMouse.y = newMouse.y; newMouse.x += dMouse.x; newMouse.y += dMouse.y; // NXLogError("old == (%f, %f) new == (%f, %f)\n", oldMouse.x, oldMouse.y, newMouse.x, newMouse.y); return self; } - animateScale { return self; } - animateTranslate { return self; } - animateClick { if (animateRotate) { [self animateRotate]; } if (animateScale) { [self animateScale]; } if (animateTranslate) { [self animateTranslate]; } [self display]; return self; } void animateHandler(DPSTimedEntry teNumber, double now, void *userData) { id myObj = (id)userData; [myObj animateClick]; return ; } - removeRenderTE { if (renderTE) { DPSRemoveTimedEntry(renderTE); renderTE = 0; renderCount = 0; backgroundRendering = NO; } return self; } - setBackgroundRenderingOff { [self removeRenderTE]; return self; } - (BOOL)backgroundRendering { return backgroundRendering; } - backgroundRender { if (!backgroundRendering) { renderCount++; if (renderCount == renderAtMediumRate) { NXLogError("starting medium render...\n"); backgroundRendering = YES; [delegate setRenderStartTime]; [self renderAsTIFF]; } if (renderCount == renderAtHighRate) { NXLogError("starting high render...\n"); backgroundRendering = YES; [delegate setRenderStartTime]; [self renderAsTIFF]; } } return self; } void renderHandler(DPSTimedEntry teNumber, double now, void *userData) { id myObj = (id)userData; [myObj backgroundRender]; return ; } //////////////////////////////////////////////////////////////////// // So user can get some feedback /////////////////////////////////////////////////////////////////// static void getRegion(NXRect *region, const NXPoint *p1, const NXPoint *p2) /* * Returns the rectangle which has p1 and p2 as its corners. */ { region->size.width = p1->x - p2->x; region->size.height = p1->y - p2->y; if (region->size.width < 0.0) { region->origin.x = p2->x + region->size.width; region->size.width = ABS(region->size.width); } else { region->origin.x = p2->x; } if (region->size.height < 0.0) { region->origin.y = p2->y + region->size.height; region->size.height = ABS(region->size.height); } else { region->origin.y = p2->y; } } - updateShapeForInteraction:(BOOL)provideUpdates whenTracking:(BOOL)trackShape { updateShape = provideUpdates; updateWhenTracking = trackShape; return self; } - shouldChangeSelected:(BOOL)changeSelected { changeSelectedShape = changeSelected; return self; } // setCurrentShape:theShape #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK|NX_ALTERNATEMASK|NX_CONTROLMASK|NX_COMMANDMASK) - mouseDown:(NXEvent *)theEvent { int oldMask; //NXPoint p, last, start; //NXRect visibleRect, oldRegion; NXPoint start; RtPoint myEyePoint, previousEyePoint, previousViewPoint; float previousRoll; //NXRect selectionRect; long tmpUsec; struct timeval renderStartTime, renderFinishTime; char timeBuf[256]; struct timeval elapsedTime; int frameCount = 0; float currentFPS; [self removeAnimateTE]; [self removeRenderTE]; if (image) { [image free]; image = nil; } dMouse.x = 0.0; dMouse.y = 0.0; // track the mouse until a mouseUp event occurs, updating the display // as tracking happens. [self lockFocus]; oldMask = [window addToEventMask:ACTIVEBUTTONMASK]; // switch to the N3D_WireFrame surface type [self setSurfaceTypeForAll:movingRenderStyle chooseHider:YES]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, lowRezTesselationVector, RI_NULL); oldMouse = theEvent->location; [self convertPoint:&oldMouse fromView:nil]; start = oldMouse; /* * Update the current shape should changeSelectedShape be enabled. * setCurrentShape to be complete, or setNoCurrentShape should * the mouseDown occur outside of any bounding box (for those * shapes that are selectable). */ if (changeSelectedShape) { id theShape = worldShape; NXRect boundingRect; while (theShape) { if ([theShape conformsTo:@protocol(WWRenderable)]) { (void)[theShape boundingBox]; } [theShape getBounds:&boundingRect inCamera:self]; if (NXPointInRect(&start, &boundingRect)) { [self setCurrentShape:theShape]; break; } theShape = [theShape nextPeer]; } if (!theShape) { [self setNoCurrentShape:self]; } #if 0 List *selected; NXSetRect(&selectionRect, start.x, start.y, 10.0, 10.0); selected = [self selectShapesIn:&selectionRect]; if ([selected count] == 0) { [self setNoCurrentShape:self]; } else { [self setCurrentShape:[selected objectAt:0]]; } #endif } // when the alt key is depressed, we scale the worldShape up or down, depending on mouse movement. // otherwise, we rotate the worldShape using the virtual trackball gettimeofday(&renderStartTime, 0); while (1) { newMouse = theEvent->location; [self convertPoint:&newMouse fromView:nil]; dMouse.x = newMouse.x - oldMouse.x; dMouse.y = newMouse.y - oldMouse.y; if (dMouse.x != 0.0 || dMouse.y != 0.0) { if (theEvent->flags & NX_ALTERNATEMASK) { switch (trackballAffects) { case WW_TRACKBALL_WORLD_SHAPE: sprintf(statusBuf, "translating world in Z by %f", (translateZFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [worldShape translate:0.0 :0.0 :(translateZFactor * dMouse.y)]; break; case WW_TRACKBALL_CURRENT_SHAPE: sprintf(statusBuf, "translating %s in Z by %f", [currentShape shapeName], (translateZFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [currentShape translate:0.0 :0.0 :(translateZFactor * dMouse.y)]; break; case WW_TRACKBALL_CAMERA: // need to change Eye point sprintf(statusBuf, "moving eye point in Z by %f", (translateZFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [self moveEyeBy:0.0 :0.0 :(-1. * (translateZFactor * dMouse.y))]; break; } } else { if (theEvent->flags & NX_CONTROLMASK) { // NOTE draw rubber band selection here getRegion(&selectionRegion, &newMouse, &start); [statusText setStringValue:"selecting crop region for rendering..."]; [statusText display]; NXPing(); //NXInsetRect(&oldRegion, -1.0, -1.0); //oldRegion = selectionRegion; // last = p; } else { if (theEvent->flags & NX_COMMANDMASK) { switch (trackballAffects) { case WW_TRACKBALL_WORLD_SHAPE: sprintf(statusBuf, "translating world in X & Y by (%f, %f)", (translateXFactor * dMouse.x), (translateYFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [worldShape translate:(translateXFactor * dMouse.x) :(translateYFactor * dMouse.y) :0.0]; break; case WW_TRACKBALL_CURRENT_SHAPE: sprintf(statusBuf, "translating %s in X & Y by (%f, %f)", [currentShape shapeName], (translateXFactor * dMouse.x), (translateYFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [currentShape translate:(translateXFactor * dMouse.x) :(translateYFactor * dMouse.y) :0.0]; break; case WW_TRACKBALL_CAMERA: sprintf(statusBuf, "moving eye in X & Y by (%f, %f)", (translateXFactor * dMouse.x), (translateYFactor * dMouse.y)); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [self moveEyeBy:(-1. * (translateXFactor * dMouse.x)) :(-1. * (translateYFactor * dMouse.y)) :0.0]; break; } } else { [theRotator trackMouseFrom:&oldMouse to:&newMouse rotationMatrix:rmat andInverse:irmat]; switch (trackballAffects) { case WW_TRACKBALL_WORLD_SHAPE: sprintf(statusBuf, "rotating world..."); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [worldShape concatTransformMatrix:rmat premultiply:YES]; break; case WW_TRACKBALL_CAMERA: sprintf(statusBuf, "rotating camera..."); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [self getEyeAt:&previousEyePoint toward:&previousViewPoint roll:&previousRoll]; myEyePoint[0] = previousEyePoint[0] + (-1. * (translateXFactor * dMouse.x)); myEyePoint[1] = previousEyePoint[1] + (-1. * (translateYFactor * dMouse.y)); myEyePoint[2] = previousEyePoint[2]; [self setEyeAt:myEyePoint toward:previousViewPoint roll:previousRoll]; break; case WW_TRACKBALL_CURRENT_SHAPE: sprintf(statusBuf, "rotating %s...", [currentShape shapeName]); [statusText setStringValue:statusBuf]; [statusText display]; NXPing(); [currentShape concatTransformMatrix:rmat premultiply:YES]; break; } } } } if (updateShape && updateWhenTracking) { if (trackballAffects == WW_TRACKBALL_WORLD_SHAPE) { [worldShape performUpdateForInteraction:self]; } else if (trackballAffects == WW_TRACKBALL_CURRENT_SHAPE) { [currentShape performUpdateForInteraction:self]; } } [self display]; NXPing(); } theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK]; if (theEvent->type == NX_MOUSEUP) { break; } else { oldMouse = newMouse; } frameCount++; } gettimeofday(&renderFinishTime, 0); [statusText setStringValue:"done"]; [statusText display]; NXPing(); elapsedTime.tv_sec = renderFinishTime.tv_sec - renderStartTime.tv_sec; tmpUsec = renderFinishTime.tv_usec - renderStartTime.tv_usec; if (tmpUsec < 0) { elapsedTime.tv_sec--; elapsedTime.tv_usec = (long)1000000 + tmpUsec; } else { elapsedTime.tv_usec = tmpUsec; } if (elapsedTime.tv_usec > (long)1000000) { elapsedTime.tv_sec++; elapsedTime.tv_usec -= (long)1000000; } if (frameCount) { currentFPS = (float)frameCount/((float)elapsedTime.tv_sec + ((float)(elapsedTime.tv_usec)/1000000.)); sprintf(timeBuf, "%f fps: %d frames in %d.%d seconds", currentFPS, frameCount, (int)(elapsedTime.tv_sec), (int)((1000000 - elapsedTime.tv_usec)/100000)); [statusText setStringValue:timeBuf]; [statusText display]; NXPing(); } // check to see if we should go off and render (need a minimum image size, like 16x16)... // check to see if we should keep rotating or scaling... // if mouse was moving significantly, keep going... if (((float)fabs((double)(dMouse.x)) > epsilon) || ((float)fabs((double)dMouse.y) > epsilon)) { // comment out for now... //animateTE = DPSAddTimedEntry(.002, (DPSTimedEntryProc)animateHandler, self, NX_BASETHRESHOLD); //animateRotate = YES; [self setSurfaceTypeForAll:renderStyle chooseHider:YES]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); } else { animateTE = 0; animateRotate = NO; // switch back to the N3D_SmoothSolids surface type [self setSurfaceTypeForAll:renderStyle chooseHider:YES]; RiGeometricApproximation(RI_TESSELATION, RI_PARAMETRIC, tesselationVector, RI_NULL); //renderTE = DPSAddTimedEntry(renderCheckTimeSlice, (DPSTimedEntryProc)renderHandler, self, NX_BASETHRESHOLD); } if (updateShape) { if (trackballAffects == WW_TRACKBALL_WORLD_SHAPE) { [worldShape performUpdateForInteraction:self]; } else if (trackballAffects == WW_TRACKBALL_CURRENT_SHAPE) { [currentShape performUpdateForInteraction:self]; } } [self display]; [self unlockFocus]; [window setEventMask:oldMask]; [window flushWindow]; return self; } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)acceptsFirstMouse { return YES; } - keyDown:(NXEvent *)theEvent { // id theCmd = nil; // what we want to be able to do is have a set of mappings from the // charCode to some piece of tcl code. // We also want to be able to have the tcl code be executed in either // the camera's interp or the shape interp... // we'll say that if the cmd key is held down, it goes to the camera, // otherwise we send it to the root shape's interp. // we should probably have a hash table which has two things: // the charCode and the tcl code that corresponds to it // if there isn't an entry, drop through... // if (theEvent->flags & NX_COMMANDMASK) // the command key is being held down : camera! // { theCmd = [self cameraCmdFromCharCode:theEvent->data.key.charCode]; // if (theCmd) // { [tclInterp globalEval:[theCmd str]]; // } // [delegate controlsWereUpdated:self]; // return self; // } // else // must want to talk to the model, I guess... // { theCmd = [self modelCmdFromCharCode:theEvent->data.key.charCode]; // if (theCmd) // { [[rootShape tclInterp] globalEval:[theCmd str]]; // } // [delegate controlsWereUpdated:self]; // return self; // } return [super keyDown:theEvent]; } - takeRenderWorldAsBox:sender { drawWorldAsBox = [sender intValue]; [worldShape setDrawAsBox:drawWorldAsBox]; return [self display]; } - takeRenderCurrentAsBox:sender { drawCurrentAsBox = [sender intValue]; [currentShape setDrawAsBox:drawCurrentAsBox]; return [self display]; } - takeWorldIsVisible:sender { [worldShape setVisible:[sender intValue]]; return [self display]; } - takeCurrentIsVisible:sender { [currentShape setVisible:[sender intValue]]; return [self display]; } - (BOOL)renderWorldAsBox { return [worldShape doesDrawAsBox]; } - (BOOL)renderCurrentAsBox { return [currentShape doesDrawAsBox]; } - (BOOL)worldIsVisible { return [worldShape isVisible]; } - (BOOL)currentIsVisible { return [currentShape isVisible]; } - (int)trackballAffects { return trackballAffects; } - takeTrackballAffectsFromMatrix:sender { int newVal = [[sender selectedCell] tag]; switch (newVal) { case WW_TRACKBALL_WORLD_SHAPE: trackballAffects = newVal; [self setUsePreTransformMatrix:NO]; break; case WW_TRACKBALL_CAMERA: // we assume that [self usesPreTransformMatrix] returns YES... trackballAffects = newVal; [self setUsePreTransformMatrix:YES]; break; case WW_TRACKBALL_CURRENT_SHAPE: trackballAffects = newVal; [self setUsePreTransformMatrix:NO]; break; default: NXLogError("%d is an invalid value for trackballAffects.\n", newVal); } return self; } - (int)trackballXYZ { N3DAxis theAxis = [theRotator rotationAxis]; int theAxisInt = -1; if (theAxis == N3D_AllAxes) { theAxisInt = 0; } if (theAxis == N3D_XAxis) { theAxisInt = 1; } if (theAxis == N3D_YAxis) { theAxisInt = 2; } if (theAxis == N3D_ZAxis) { theAxisInt = 3; } if (theAxis == N3D_XYAxes) { theAxisInt = 4; } if (theAxis == N3D_XZAxes) { theAxisInt = 5; } if (theAxis == N3D_YZAxes) { theAxisInt = 6; } return theAxisInt; } - takeTrackballXYZFromMatrix:sender { int newVal = [[sender selectedCell] tag]; switch (newVal) { case 0: [theRotator setRotationAxis:N3D_AllAxes]; break; case 1: [theRotator setRotationAxis:N3D_XAxis]; break; case 2: [theRotator setRotationAxis:N3D_YAxis]; break; case 3: [theRotator setRotationAxis:N3D_ZAxis]; break; case 4: [theRotator setRotationAxis:N3D_XYAxes]; break; case 5: [theRotator setRotationAxis:N3D_XZAxes]; break; case 6: [theRotator setRotationAxis:N3D_YZAxes]; break; default: NXLogError("%d is an invalid value for trackballXYZ.\n", newVal); } return self; } - tclInterp { return tclInterp; } /// new camera stuff - takeFocalLength:sender { return [self setFocalLength:[sender floatValue]]; } - takeFocalDistance:sender { return [self setFocalDistance:[sender floatValue]]; } - takeFStop:sender { return [self setFStop:[sender floatValue]]; } - takeExposureLength:sender { return [self setExposureLength:[sender floatValue]]; } - takeShotOutputTypeFromMatrix:sender { NXLogError("[WW3DCamera takeShotOutputTypeFromMatrix:sender] is not really implemented yet.\n"); shotOutputType = [[sender selectedCell] tag]; return self; } - takeShotLength:sender { return [self setShotLength:[sender floatValue]]; } - takeFramesPerSecond:sender { return [self setFramesPerSecond:[sender floatValue]]; } - takeFrameNumber:sender { return [self setFrameNumber:[sender intValue]]; } - takeExposureLengthFactor:sender { return [self setExposureLengthFactor:[sender floatValue]]; } - takeShotStartTime:sender { return [self setShotStartTime:[sender floatValue]]; } - setRenderStyle:(int)s { renderStyle = s; [self setSurfaceTypeForAll:renderStyle chooseHider:YES]; [self display]; return self; } - (int)renderStyle { return renderStyle; } - setMovingRenderStyle:(int)s { movingRenderStyle = s; return self; } - (int)movingRenderStyle { return movingRenderStyle; } - (NXColor) backgroundColor { return backgroundColor; } - setBackgroundColor:(NXColor)c { backgroundColor = c; [self display]; return self; } - (BOOL)showSelectedShape { return showSelectedShape; } - setShowSelectedShape:(BOOL)flag { showSelectedShape = flag; [currentShape setSelected:flag andDrawOrigin:drawOriginForSelectedShape]; [self display]; return self; } - setSceneClock:newSceneClock { sceneClock = newSceneClock; return self; } - sceneClock { return sceneClock; } - (BOOL)drawOriginForSelectedShape { return drawOriginForSelectedShape; } - setDrawOriginForSelectedShape:(BOOL)flag { drawOriginForSelectedShape = flag; [currentShape setDrawOrigin:flag]; [self display]; return self; } - otherLightList { return otherLightList; } - addLocalLight:light usingPath:(const char *)aParentPath { id theLightParent = [[self worldShape] getChildGivenPath:aParentPath]; if (theLightParent) { [theLightParent addChild:light]; [otherLightList addObject:light]; return self; } return nil; } - setStatusText:newStatusText { statusText = newStatusText; return self; } - statusText { return statusText; } - (BOOL)useRendribInstead { return useRendribInstead; } - setUseRendribInstead:(BOOL)n { useRendribInstead = n; return self; } - takeUseRendribInstead:sender { useRendribInstead = [sender intValue]; return self; } - (BOOL)binaryRIB { return binaryRIB; } - setBinaryRIB:(BOOL)n { binaryRIB = n; return self; } - takeBinaryRIB:sender { binaryRIB = [sender intValue]; return self; } #define typeVectorVersion1 "i*ffffffff@[2f][2f]fiifcci@cffffffff@@@" #define typeValuesVersion1 &renderStyle, &ribName, \ &scaleUpFactor, &scaleDownFactor, &translateXFactor, &translateYFactor, &translateZFactor, \ &epsilon, &selectionWidthEpsilon, &selectionHeightEpsilon, \ &image, &lowRezTesselationVector, &tesselationVector, &shadingRate, \ &renderAtMediumRate, &renderAtHighRate, &renderCheckTimeSlice, &showSelectedShape, &drawOriginForSelectedShape, \ &movingRenderStyle, &tclInterp, &defaultLightsInUse, \ &fStop, &focalLength, &focalDistance, &shutterOpenTime, &exposureLength, &frameTimeIncrement, &shotLength, &framesPerSecond, \ &ambientLight, &leftLight, &rightLight #define typeVectorVersion2 "i*ffffffff@[2f][2f]fiifcci@cffffffff@@@" #define typeValuesVersion2 &renderStyle, &ribName, \ &scaleUpFactor, &scaleDownFactor, &translateXFactor, &translateYFactor, &translateZFactor, \ &epsilon, &selectionWidthEpsilon, &selectionHeightEpsilon, \ &image, &lowRezTesselationVector, &tesselationVector, &shadingRate, \ &renderAtMediumRate, &renderAtHighRate, &renderCheckTimeSlice, &showSelectedShape, &drawOriginForSelectedShape, \ &movingRenderStyle, &tclInterp, &defaultLightsInUse, \ &fStop, &focalLength, &focalDistance, &shutterOpenTime, &exposureLength, &frameTimeIncrement, &shotLength, &framesPerSecond, \ &ambientLight, &leftLight, &rightLight #define typeVectorVersion3 "i*ffffffff@fiifcci@cffffffff@@@" #define typeValuesVersion3 &renderStyle, &ribName, \ &scaleUpFactor, &scaleDownFactor, &translateXFactor, &translateYFactor, &translateZFactor, \ &epsilon, &selectionWidthEpsilon, &selectionHeightEpsilon, \ &image, &shadingRate, \ &renderAtMediumRate, &renderAtHighRate, &renderCheckTimeSlice, &showSelectedShape, &drawOriginForSelectedShape, \ &movingRenderStyle, &tclInterp, &defaultLightsInUse, \ &fStop, &focalLength, &focalDistance, &shutterOpenTime, &exposureLength, &frameTimeIncrement, &shotLength, &framesPerSecond, \ &ambientLight, &leftLight, &rightLight #define typeVector "i*ffffffff@fiifcci@cffffffff@@@ff" #define typeValues &renderStyle, &ribName, \ &scaleUpFactor, &scaleDownFactor, &translateXFactor, &translateYFactor, &translateZFactor, \ &epsilon, &selectionWidthEpsilon, &selectionHeightEpsilon, \ &image, &shadingRate, \ &renderAtMediumRate, &renderAtHighRate, &renderCheckTimeSlice, &showSelectedShape, &drawOriginForSelectedShape, \ &movingRenderStyle, &tclInterp, &defaultLightsInUse, \ &fStop, &focalLength, &focalDistance, &shutterOpenTime, &exposureLength, &frameTimeIncrement, &shotLength, &framesPerSecond, \ &ambientLight, &leftLight, &rightLight, &shotStartTime, &exposureLengthFactor - read:(NXTypedStream *)stream { int version; [super read:stream]; NX_DURING version = NXTypedStreamClassVersion(stream, "WW3DCamera"); if (version == 0) NXReadTypes(stream,"i",&version), version=1; if (version == 1) { NXReadTypes(stream, typeVectorVersion1, typeValuesVersion1); backgroundColor = NXReadColor(stream); ribColor = NXReadColor(stream); shotStartTime = 0.0; exposureLengthFactor = 1.0; binaryRIB = NO; } if (version == 2) { NXReadTypes(stream, typeVectorVersion2, typeValuesVersion2); backgroundColor = NXReadColor(stream); ribColor = NXReadColor(stream); shotStartTime = 0.0; exposureLengthFactor = 1.0; binaryRIB = YES; } if (version == 3) { NXReadTypes(stream, typeVectorVersion3, typeValuesVersion3); NXReadArray(stream, "f", 2, lowRezTesselationVector); NXReadArray(stream, "f", 2, tesselationVector); backgroundColor = NXReadColor(stream); ribColor = NXReadColor(stream); sceneClock = NXReadObject(stream); shotStartTime = 0.0; exposureLengthFactor = 1.0; binaryRIB = NO; } if (version == 4) { NXReadTypes(stream, typeVector, typeValues); NXReadArray(stream, "f", 2, lowRezTesselationVector); NXReadArray(stream, "f", 2, tesselationVector); backgroundColor = NXReadColor(stream); ribColor = NXReadColor(stream); sceneClock = NXReadObject(stream); binaryRIB = NO; } if (version == 5) { NXReadTypes(stream, typeVector, typeValues); NXReadArray(stream, "f", 2, lowRezTesselationVector); NXReadArray(stream, "f", 2, tesselationVector); backgroundColor = NXReadColor(stream); ribColor = NXReadColor(stream); sceneClock = NXReadObject(stream); NXReadType(stream, "c", &binaryRIB); } NX_HANDLER NXLogError("in read: %s, exception [%d] raised.\n", [[self class] name], NXLocalHandler.code); return nil; NX_ENDHANDLER return self; } - write:(NXTypedStream *)stream { [super write:stream]; exposureLength = savedExposureLength; // just to make sure we archive it... NXWriteTypes(stream, typeVector, typeValues); NXWriteArray(stream, "f", 2, lowRezTesselationVector); NXWriteArray(stream, "f", 2, tesselationVector); NXWriteColor(stream, backgroundColor); NXWriteColor(stream, ribColor); NXWriteObjectReference(stream, sceneClock); NXWriteType(stream, "c", &binaryRIB); return self; } @end